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.
Related
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.
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.
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.
I am trying to understand the concept of synchronizing on an object. Using this example from the Java Cert Book, can you help me understand the difference in behavior between the following 2 pieces of code (one where we synchronize on the object whose methods/operations we want to protect from the race condition and another where we use a helper object as a lock to achieve the same goal):
1.
class Client {
BankAccount account;
public void updateTransaction() {
synchronized (account) {
account.update(); // update is safe because of lock on account obj
}
}
public double withdrawFunds() {
double amt;
synchronized (account) {
account.calculateInterest();
amt= account.withdraw();
}
return amt;
}
}
2.
class Client {
BankAccount account;
Object lock = new Object();
public void updateTransaction() {
synchronized (lock) {
account.update(); // update is safe because of a lock
}
}
public double withdrawFunds() {
double amt;
synchronized (lock) {
account.calculateInterest();
amt= account.withdraw();
}
return amt;
}
}
Both of those will throw NullPointerExceptions, but only in different places.
You should always synchronize on an immutable reference that will never be null (final).
I guess the answer to your question is that account will potentially change for a given client (assuming there is a setter) but lock never should. Again, the only way to guarantee that is to mark it final.
A better approach is to avoid exposing locking when it can be encapsulated.
class Client {
final BankAccount account;
public void updateTransaction() {
account.update(); // update is synchonized.
}
public double withdrawFunds() {
return account.calculateInterestAndWithdraw();
}
}
The difference is with respect to what other threads are doing in your system. In the first case, if there are any reasons why some other logic (defined in some other code) should not be exercised concurrently with the updateTransaction method, that logic could also be synchronized on the account object. Conversely, you might have a false synchronization if some unrelated code also uses account as the lock when it has nothing to do with updateTransaction.
In the second case, the lock object is only visible to the Client class, so you are guaranteed that the only synchronization that goes on is what you have specified in this class.
I agree with Peter Lawrey that the best approach is to encapsulate the synchronization logic in a single place where it makes sense, and use private/protected visibility lock objects for that.
In those two cases, there is no difference, but a stylistic difference.
If account could be changed, there is a potential problem that could be synchronizing on the wrong object. Make that property final and you're good to go.
The difference is who holds the Lock.
The first case is the better, because the same reference to account could be in also shared in other thread, for example in the class Manager, and if this manager needs to access the account, should try to hold the lock himself in any case that the Client thread tries to access the account at the same time.
In the second code, the Manager needs to lock on the lock object, for preventing doing damage to the data, so its needs to get the account and the lock.
The best approach is to encapsulate the lock inside account.
I would use option 2, just make the lock object final. The account object can probably be changed, especially if the client can have more than one account. If you use a final lock object you will ensure that any change to the account is synchronized, even if the account object changes to a different instance.
In a nice article with some concurrency tips, an example was optimized to the following lines:
double getBalance() {
Account acct = verify(name, password);
synchronized(acct) { return acct.balance; }
}
If I understand that correctly, the point of the synchronization is to ensure that the value of acct.balance that are read by this thread is current and that any pending writes to the fields of the object in acct.balance are also written to main memory.
The example made me think a little: wouldn't it be more efficient to just declare acct.balance (i.e. the field balance of class Account) as volatile? It should be more efficient, save you all the synchronize on accesses to acct.balance and would not lock the whole acct object. Am I missing something?
You are correct. volatile provides a visibility guarantee. synchronized provides both a visibility guarantee AND serialisation of protected code sections. For VERY simple situations volatile is enough, however it is easy to get into trouble using volatile instead of synchronisation.
If you were to assume that Account has a way of adjusting its balance then volatile is not good enough
public void add(double amount)
{
balance = balance + amount;
}
Then we have a problem if balance is volatile with no other synchronization. If two threads were to try and call add() together you could have a "missed" update where the following happens
Thread1 - Calls add(100)
Thread2 - Calls add(200)
Thread1 - Read balance (0)
Thread2 - Read balance (0)
Thread1 - Compute new balance (0+100=100)
Thread2 - Compute new balance (0+200=200)
Thread1 - Write balance = 100
Thread2 - Write balance = 200 (WRONG!)
Obviously this is wrong because both threads read the current value and updated independently and then wrote it back (read, compute, write). volatile does not help here so you would need synchronized to ensure one thread completed the entire update before the other thread began.
I general find that if when writing some code I think "can I use volatile instead of synchronized" the answer might well be "yes" but the time/effort of figuring it out for sure and the danger of getting it wrong is not worth the benefit (minor performance).
As an aside a well written Account class would handle all the synch logic internally so callers don't have to worry about it.
Declaring Account as volatile is subjected to following issues and restrictions
1."Since other threads cannot see local variables, declaring local variables volatile is futile." Moreover If you try to declare a volatile variable in a method, you'll get a compiler error in some cases.
double getBalance() {
volatile Account acct = verify(name, password); //Incorrect ..
}
Declaring Account as volatile warns the compiler to fetch them fresh each time, rather than caching them in registers. This also inhibits certain optimizations that assume no other thread will change the values unexpectedly.
If you need synchronized to co-ordinate changes to variables from different threads,
volatile does not guarantee you atomic access,because accessing a volatile variable never holds a lock, it is not suitable for cases where we want to read-update-write as an atomic operation. Unless you are sure that acct = verify(name, password); is single atomic operation, you cannot guarantee excepted results
If variable acct is an object reference, then chances are it may be null .Attempting to synchronize on a null object will throw a NullPointerException using synchronized.
(because you're effectively synchronizing on the reference, not the actual object)
Where as volatile does not complain
Instead you could declare a boolean variable as volatile like here
private volatile boolean someAccountflag;
public void getBalance() {
Account acct;
while (!someAccountflag) {
acct = verify(name, password);
}
}
Note you cannot declare someAccountflag as synchronized, as
you can't synchronize on a primitive with synchronized, synchronized only works with object variables, where as primitive or object variable may be declared volatile
6.Class final static fields doesn't need to be volatile, JVM takes care of this problem. So the someAccountflag need not be even declared volatile if it is a final static
or you could use lazy singleton initialization making Account as a singleton object
and declare it as follows:
private final static AccountSingleton acc_singleton = new AccountSingleton ();
If multiple threads are modifying and accessing the data, synchronized guarantees data consistency among multiple threads .
if single thread is modifying the data and multiple threads try to read the latest value of data, use volatile construct.
But for above code, volatile does not guaranty memory consistency if multiple threds modify balance. AtomicReference with Double type serves your purpose.
Related SE question:
Difference between volatile and synchronized in Java