Java synchronized blocks using specific object reference - java

I'm using the code below to block concurrent access to an Auction object. It gets the object from a hash map so it operates on a wide range of different Auctions.
I've used a synchronized block with a reference to the individual Auction object chosen as the parameter. I'm under the impression that this holds the lock from the objects monitor and will block access to threads also using the same auction (until the first case has finished).
Can anyone confirm that this code is acting in a way that 1) If two thread both reference auction A then only one may proceed at time 2) If one thread references Auction A and another Auction B then they both proceed as they acquire different locks.
//Get auction from hashmap
Auction biddingAuction = (Auction) auctions.get(ID);
//Check that auction is active
if(biddingAuction != null)
{
//Acquire lock on Auction object
synchronized(biddingAuction) {
//Some code that alters values of Auction
}
} else {
return "\nBid failed - no auction with an ID of " + ID + " was found\n";
}
any clarity would be appreciated, thanks

Can anyone confirm that this code is acting in a way that 1) If two thread both reference auction A then only one may proceed at time
No. Both threads would have to synchronize on the Auction to have that guarantee. If one thread doesn't synchronize, it can access the auction even if another thread holds its lock.
That's why such a way of doing is very fragile: if you ever forget to synchronize before accessing the Auction's mutable shared state (whether it write it or reads it), your code isn't thread-safe. A much cleaner way would be to make the Auction class itself thread-safe, by properly synchronizing the methods that access its shared mutable state.
If one thread references Auction A and another Auction B then they both proceed as they acquire different locks.
Yes. That is correct.

Related

Java synchronize a class instance

I can't seem to find any example of what I want to ask:
Let's say I have in class Account
public void transferMoney(Account fromAccount, Account toAccount, DollarAmount amountToTransfer) {
if (fromAccount.hasSufficientBalance(amountToTransfer) {
fromAccount.debit(amountToTransfer);
toAccount.credit(amountToTransfer);
}
}
this may cause a race condition when used in an overriden run method, and I have this code in Main:
Account acc1 = new Account(..);
Account acc2 = new Account(..);
Thread t1 = new Thread(new Transfer(..from acc1 to acc2..));
Thread t2 = new Thread(new Transfer(..from acc2 to acc1..));
synchronized (acc1) {
t1.start();
}
synchronized (acc2) {
t2.start()
}
Synchronizing these two instances of Account acc1 and acc2 does not prevent the Race Condition, but I don't know why or what synchronizing does exactly in this case!
I couldn't find any example about this kind of synchronize.
synchronized only has an effect if a thread tries to enter a synchronized block while another thread currently is in a synchronized block referring to the same object. Here, only your main thread synchronizes on acc1 and acc2, hence no synchronization will actually take place.
A better design for your case would be to aggregate hasSufficientBalance and debit into a single method, which is synchronized (which is equivalent to the whole method body being enclosed in a synchronized(this) block). This synchronized serves to protect the internal state of the class. Therefore, you will also want to mark the credit method as synchronized.
public synchronized boolean debitIfHasSufficientBalance(DollarAmount amount) {
if (hasSufficientBalance(amount)) {
debit(amount);
return true;
}
return false;
}
Your transferMoney could then be rewritten as following, without any explicit synchronization:
public void transferMoney(Account fromAccount, Account toAccount, DollarAmount amountToTransfer) {
if (fromAccount.debitIfHasSufficientBalance(amountToTransfer)) {
toAccount.credit(amountToTransfer);
}
}
When you say:
synchronized (acc1) {
t1.start();
}
that causes the current thread to try to acquire the lock on the object acc1, then, once it has that lock, the current thread starts the thread t1. At that point t1's run method gets called in a new thread, and that new thread can do whatever it wants, it's not subject to any locking. You don't lock a thread as such, threads work by acquiring locks that give them access to shared data. When a thread tries to enter a synchronized block that another thread has acquired the lock for, it has to block until it can get the lock.
Synchronizing doesn't do anything unless the different threads are locking on something that's shared. Here one thread locks on one object and the other thread locks on a different object, so there is no effect.
It would seem like you'd want a lock on acc1 and on acc2:
synchronized (acc1) {
synchronized (acc2) {
... now do the transfer
}
}
This creates problems because you have to get the locks in the same order or risk deadlock.
Also it depends on the instances of acc1 and acc2 being shared among the different threads; if different threads instantiate their own copies (for instance with Hibernate each thread would have its own session and would make its own copy of any persistent entities) this won't work.
In real life you wouldn't do this; for things like account transfers you'd probably use database locking or transactions for this, where the database is the shared resource that limits access. Toy examples can cause confusion sometimes because people get distracted picking apart the toy example. A real-life situation where you would see synchronization is on collections (lists, maps, queues, etc.) that need to be accessed by multiple threads.
Well, you probably don't want Account objects to be in charge of transferring money among themselves. Instead I would recommend implementing some sort of controller object, which facilitates the transfers.
To ensure your controller object can only have a single instance, a good way to go about this is to make it an Enum, which brings along the synchronization stuff "for free" as Josh Bloch would say.
http://www.informit.com/articles/article.aspx?p=1216151&seqNum=3
http://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-with-examples
http://javarevisited.blogspot.com/2012/07/why-enum-singleton-are-better-in-java.html
Remember, with an Enum, there is only ever one that exists in your program, so if you call it from two different threads, one will be blocked until the Enum is released by the other caller. This happens automagically with Enum objects.
public Enum AccountController {
MyBankProgram,
;
/**
* Transfers DollarAmount from Account a to Account b.
*/
public void transferFunds(final Account a, final Account b, DollarAmount d) {
// do stuff here
a.subtract(d);
b.add(d);
}
}
This would be used as:
AccountController.MyBankProgram.transferFunds(accountA, accountB, new DollarAmount("45.00"));
then your Account objects would only need publically exposed methods of:
public void add(final DollarAmount n);
public void subtract(final DollarAmount n);
And I would recommend these go through your controller object and not be called from anywhere else, you don't want random pieces of code adding or removing funds!
I do not really understand what do these synchronized locks exactly lock?
They don't lock anything. "Lock" is a very misleading name in this context.
The synchronized keyword does one thing, and one thing only: It prevents two or more threads from synchronizing on the same object at the same time.
See #misberner 's answer for a good solution to your problem.

Warranty of storing variable value before next command in java

I am curious if immediately after value assign command like this:
a = 5;
there is a warranty that the new value has been stored into variable? And if this is different for primitive and other data types? And especially with Runnable objects.
I have run method in MyClass containing:
synchronized(this){
while(pleaseWait){
try { System.out.println("sleeping"); wait();}
catch (Exception e) { e.printStackTrace(); }
}
}
is other classes i am calling method sleepMe() which contains:
synchronized (myclass){
myclass.pleaseWait = true;
myclass.notify();
}
And the question is, do I have to insert waiting after calling sleepMe, so the instance of MyClass have time to change value of myclass.pleaseWait ?
I have several set methods, where I assing complex objects (objects of objects) to instance of MyClass.
Thanks
The fact that you the two threads are synchronizing on the same object means that the changes made to pleaseWait by one thread will be visible to the other thread when it returns from the wait() call. The synchronization (in this case the regaining of the lock on this when you return from the wait() call) provides the required "happens before" relationship between the two threads to ensure that the update is visible.
So to answer your question:
Any solution requires one thread to "wait" in some sense. That's inherent in the problem.
What you are doing is sufficient. You don't need to add additional waiting. The wait/notify mechanism ensures that the thread that does the wait() will see an up-to-date copy of the variable ... provided that all changes are made while holding that object lock.
You can also implement this kind of thing using higher level concurrency classes.
You could also implement this using a volatile and "busy waiting" ... but that would be a really BAD IDEA.

How to efficiently lock a code block in order to avoid optimistic lock exception

I am not very experienced with Multithreading in Java. What I want is to set a lock for a code block. In my case i want to avoid optimistic lock exceptions, while doing some synchronization for a certain user. The method replicateUser can be called by multiple threads for the same user. But it is not guaranteed, that authenticatedUser is always the same identical object.
So how can I effeciently lock this section? What I don't want is, that the section is locked for all threads, but only for those with the same user. Can I put a lock on string objects as shown on the example below using getUserName()?
private void replicateUser(AuthenticatedUser authenticatedUser) {
//
// How to synchronize the following block correctly?
//
synchronized (authenticatedUser.getUserName()) {
User dbUser = userRepository.findOne(authenticatedUser.getUserName());
if (!checkIsUserReplicated(authenticatedUser, dbUser)) {
doReplication(dbUser);
}
}
}
You better put lock on authenticatedUser.getUserName ().intern () because it is guaranteed that once two strings are identical by contents, intern () will return the same object for them.
Also, if it is guaranteed in your system, that there is only one instance of AuthenticatedUser class with particular user name, then you can lock directly on authenticatedUser.
As you mention, synchronizing on authenticatedUser.getUserName() will not work because you may have multiple instances of authenticatedUser. Two threads reading in the same authenticatedUser data will get different instances if read from different EntityManager context. To get around this, you can either account for the occasional optimistic lock exception by wrapping your doReplication method with a try/catch block that then checks that the change was made by another thread (using em.refresh), or you can switch to using pessimistic locking as described here:
http://wiki.eclipse.org/EclipseLink/Examples/JPA/Locking#Pessemistic_Locking
http://wiki.eclipse.org/EclipseLink/Examples/JPA/PessimisticLocking
Once you've locked the authenticatedUser, you can check if it was replicated and release the lock or perform the replication.

How does ATM work in concurrent environment

A simple example:
class Account{
private String account_name;
private String password;
private double balance;
public synchronized double getBalance(){
return balance;
}
public synchronized void setBalance(double add){
balance += add;
}
}
From my understanding that acquiring the lock associated with an object does not prevent other threads from accessing that object. They have to be the same lock to prevent accessing.
So if two person tried accessing the same account at different ATM, then it will create two different instances of this Account object, correct ? so then it's not guarded with the same lock, right ?
lets say if Person A (Thread A) tried to save money into the account while at the same time Person B(Thread B) tried getting to total balance of the account.
How does it work ? Do they cache the Account while be using so it will return the same Account object when the next request comes in ?
Synchronized methods will lock the object instance. However, if there is a method, which is not synchronized concurrent access can happen.
ATM machines don't access your account - the bank server does. The ATM machine is just a client. So accessing the same account from 2 different ATMs would be guarded by the bank server, which has only one instance of this account in it's memory / database (probably protected by some locking mechanism and not written in Java).
It depends on the way the system is implemented. Usually you have instances of a class and each instance has an implicit lock associated with it OR you can create a simple
private Object lock;
and then everyone (be it ATM or a bank employee or something else) MUST explicitly acquire this lock. At the end of the day it boils down how the system is designed and implemented - locking primitives are just that - primitives. It is up to the designer/implemented to make use of the and to utilize them appropriately in EVERY component - consistent locking. Furthermore in this case I'd go for an atomic double and save the trouble of acquiring a potentially heavy object lock.
My best guess is they are using a object pool like cache and when ever request comes it will search particular object(Account) exist in the pool by using some unique identifier like account number. If it exist reference will be returned. Other wise it will be loaded from persistent datasource to the pool and new reference will be created and returned. So even two users(threads) try to access it sametime. Server will not create two instances for each of them.
Secondly if there are multiple synchronzied methods with in a class and if a thread is currently executing inside a synchronized method all the other threads trying to access any synchronized method for same object will be blocked(suspended execution) until first thread exists the synchronized method.
From my understanding that acquiring the lock associated with an object does not prevent other threads from accessing that object. They have to be the same lock to prevent accessing.
Correct. If multiple threads attempt to acquire a simple lock, then only on will be allowed to proceed. Locks do not necessarily need to be associated with a single object though. You can creates locks for other tasks as well.
So if two person tried accessing the same account at different ATM, then it will create two different instances of this Account object, correct ? so then it's not guarded with the same lock, right ? lets say if Person A (Thread A) tried to save money into the account while at the same time Person B(Thread B) tried getting to total balance of the account. How does it work ? Do they cache the Account while be using so it will return the same Account object when the next request comes in ?
Sort of, what you're describing is a distributed locking scenario, which is quite different. As somebody already mentioned, the ATM will send the transaction back for processing at the bank, and the servers there will handle concurrency issues.

Java: What, if anything, is locked by synchronized methods apart from the object they belong to?

Now, I'm not sure whether this is a stupid question, please bear with me if it is.
Is the lock on an object "recursive", i. e. if two objects have references to a third object in their fields and a thread is running a synchronized method on one of the two, can any other thread access the third object?
// a and b are some objects that implement Runnable
// they both reference the same third object
a.ref = c;
b.ref = c;
// a is run in a thread and processes some data in a loop for a long time
// the method the loop belongs to is declared synchronized
threadA = new Thread(a);
threadA.start();
a.someSyncedMethod(); // this would block ...
b.ref.someOtherSyncedMethod(); // ... but would this?
a.ref.someOtherSyncedMethod(); // ... and how about this?
It's worth separating out the concepts of "a lock" and "locking an object". There's no real idea of "locking an object" - there's "acquiring (and releasing)" the lock associated with an object. Yes, it sounds like I'm nitpicking - but the distinction is important because if you talk about an object being locked it sounds like no other threads will be able to change anything in the object while that lock is held.
Instead, it just means that no other thread will be able to acquire the same lock while the lock is held. There's no direct relationship between the lock and any of the contents of the object that the lock is associated with.
Methods declared "synchronized" acquire the lock associated with the instance of the object they belong to. This only makes other synchronized methods on the same object wait, and synchronized statements that explicitly sync on it.
Personally I don't like synchronized methods - I like to make it clearer by explicitly synchronizing on a (private, final) member variable which is only used for synchronization.
a.someSyncedMethod(); // this would block ...
Only if you mark either the run method with synchronized or have ThreadA run code in synchronized methods.
In the JVM, each object owns what's known as a monitor. Only one thread can own the monitor associated with a given object at a time. Synchronized is the means by which you tell the current thread to go get the monitor before continuing.
Also the class itself owns a monitor for static methods.
The meaning of a "lock" (actually this variant is called a monitor) is entirely a convention, no access restrictions are enforced.
The functioning relies on all objects being well-behaved and acquiring the corresponding lock before accessing the data. Only by encapsulating this desired behaviour within in a class with proper access controls you can enforce it for the client objects.

Categories