Win a copy of Think Java: How to Think Like a Computer Scientist this week in the Java in General forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Which option is better from scalability point of view. Synchronization, volatile or wait()/notifyAll

 
Prem Vinodh
Ranch Hand
Posts: 33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi CodeRanchers,
I do have the following question on multithreading. Unfortunately I don't have working experience on threading.
So I am posting the question along with my answers. Could your'll please let me know your views on this.

I have an Account class with the methods readBalance() and updateBalance() and a field balance.
Now if I had to synchronize the methods to avoid corrupting my balance which methods do I synchronize and why?

Ans :- I would synchronize the updateBalance() method and not the readBalance() method
Because the writers only could change the data and not the readers.

b) Now which is better option synchronizing the entrie updateBalance() or just the balance field within the method.

Ans :- I would just synchronize the balance field compared to the entire updateBalance() method as that would minimize the waiting time for the other threads.
If I were to synchronize the updateBalance() method the waiting time for the other threads would be more.

c) But if 10 threads (1 updating the balance and 9 reading the balance) are simultanesouly accessing the balance field all the 9 threads that are reading would all be waiting so this scenario is not scalable. So ideally using synchronization is not scalable so how else could I do this so that the Account class with its methods is scalable when 10 threads are accessing the Account class.

Should I use wait/notifyAll() combination or make the balance field volatile or is there some other solution which is better?
Please comment.

Thanks in advance.
Prem Vinodh

 
Anayonkar Shivalkar
Bartender
Posts: 1557
5
Eclipse IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Prem,

First of all, if you want to guarantee data safety in multi-threaded environment, you should (or rather must) make both read and write calls (i.e. readBalance and updateBalance) methods synchronized.

The problem of having only updateBalance as synchronized and readBalance as non-synchronized is:
Consider that your updateBalance method performs 5 operations on balance, and since readBalance is non-synchronized, any thread can read balance at any time. Now, what if your update thread has done only 3 out of those 5 operations, and your reader thread read that premature balance?

I think you got the problem.

Now, if you have both reader and updater methods synchronized, then you get balance either before updation, or after updation. In both cases, you'll not get corrupt balance.

Further, if you want to guarantee to read balance only after updation, then you can opt for wait/notify mechanism.

However, IMHO, volatile should not be used when data is important - especially in your case - where updateBalance might be non-atomic.

I hope this helps.
 
Steve Luke
Bartender
Posts: 4181
21
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There are a lot more options to consider then just 'synchronize the method or not'. Like Anayonkar said, you must make sure the readBalance() method provides a useful and consistent value at all times. That means it must never be able to see an intermediate value. There are a few things you can do to accomplish this without having to make readBalance() synchronized:

1) Make sure your updateBalance() method only writes its final value to the shared balance variable. If there are multiple internal calculations that change the value, those calculations should be done internal to the method and only the result assigned to the balance.

2) The balance should be assigned Atomically. How you do that depends on balance's data type, if you use something like long or float then substitute the wrappers Long or Float instead since those primitives are not atomically assigned but Objects are.

Then you have to decide if the readBalance() must absolutely present the latest balance, or if it just needs to present a reasonable snapshot of the balance. If you need the absolute latest you will need to do something to force a synchronization edge when you do readBalance(). That could be something like making it volatile.
 
Prem Vinodh
Ranch Hand
Posts: 33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Anayonkar Shivalkar/Steve Luke,

Thanks for the wonderful help your'll are providing me.
I got what your'll meant but I still have further questions.

@Anayonkar Shivalkar
Yes I believe it makes sense to me now to synchronize both the readBalance() and updateBalance() methods to get consistent values.

But I also just wanted to know if there are no threads performing updates to the balance field then the method readBalance() which if synchronized will have to execute one thread at a time (assuming there are 10 threads all trying to execute the readBalance()) which would be unnecessary.
How do I cope with this scenario?

@Steve Luke
Thanks Steve for broadening my views that I need to think in others directions too.
Otherwise I would have made the mistake of assigning intermediate values to the balance field and henceforth will keep in mind atomicity too.

And I have one last question, is synchronizing both readBalance() and writeBalance() methods a scaleable solution?
Please do let me know.

Thanks in advance
P.C. Prem Vinodh
 
Steve Luke
Bartender
Posts: 4181
21
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Prem Vinodh wrote:Hi Anayonkar Shivalkar/Steve Luke,

Thanks for the wonderful help your'll are providing me.
I got what your'll meant but I still have further questions.

@Anayonkar Shivalkar
Yes I believe it makes sense to me now to synchronize both the readBalance() and updateBalance() methods to get consistent values.

But I also just wanted to know if there are no threads performing updates to the balance field then the method readBalance() which if synchronized will have to execute one thread at a time (assuming there are 10 threads all trying to execute the readBalance()) which would be unnecessary.
How do I cope with this scenario?


Look in the java.util.concurrent.locks package. There is a ReadWriteLock which will let you take as many Read locks as you want out simultaneously, as long as there is no Write lock taken. If there is a Write lock taken, then all Reads and all other Writes are blocked until the Write is done. In your scenario the updateBalance() would use a Write lock, and the readBalance() would get the Read lock.


@Steve Luke
Thanks Steve for broadening my views that I need to think in others directions too.
Otherwise I would have made the mistake of assigning intermediate values to the balance field and henceforth will keep in mind atomicity too.

And I have one last question, is synchronizing both readBalance() and writeBalance() methods a scaleable solution?
Please do let me know.


Questions on scaleability don't have simple answers. It depends a lot on use-case, length and type of code, etc... Synchronizing points can be a bottleneck point so you have to be conscious of where they are and how they are used. But it is hard to predict (and there is no way we could predict from so far away) if the code is going to be an issue. You can't know the answer until you test and measure. If you test and then add high load on the system and it slows down, use some performance tools to find where the bottlenecks actually are. If you find they are caused by contesting synchronization locks that is the sign you need to worry more about how much and what code needs to be locked down. But to start with - just program safely.
 
Prem Vinodh
Ranch Hand
Posts: 33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Steve Luke,

Thanks for both the answers. I will take a look at the ReadWrite Lock and will see how to use it.
Yes I understand there is no easy way to decide whether the solution is scalable or not until it is actually measured.

Thanks for clarifying my doubts.

Regards
P.C. Prem Vinodh
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic