aspose file tools*
The moose likes Threads and Synchronization and the fly likes Threads behaving weirdly Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Threads behaving weirdly" Watch "Threads behaving weirdly" New topic
Author

Threads behaving weirdly

Anish Shah
Greenhorn

Joined: Sep 24, 2008
Posts: 20
Hi everyone,
I am stuck into this probelem very badly..i have never seen such a problem before..Thread bottleneck somewhere is the issue i guess,,, please have a look at the code patiently.. and do reply.. you guys are my last hope on this thing..Thank YOU...

The Bank method is called by another method which runs 50 threads , so at a time 50 threads could enter this method to record Debit...




-------------------------------------------------------------------------------------------------------------------------------




Answer:
Record time is 9014 millis for 5000 increments or 5000 calls to recordDebit()

One can see in the answer that its a huge number when one is expecting it to be somewhere around:
EXPECTED ANSWER:
5000 * 800 nanos( it takes 800 nanos for very increment) = 4000000 = 4 millis and its like 9014 millis

How is there such a huge difference ??? I have bruised thorugh it for like 3 days... i have lost all my hope.. Please help..Also look at the next code..

When i go to see in the log .. it shows me that every record took like from 2000 nanos to 6 to 7 millis i.e.7000000...
How is this even possibly possible ??? where did it get all this extra time from...it should not be more than some 700 to 900 nanos ..
Is there a bottleneck somewhere ???


Now part 2:
This thing has fazzed, dazzled , destroyed me.. I could not understand this and it has tossed all my concepts into the cupboard..

Same stuff: JUST HAVE A LOOK AND ENJOY AND TELL ME WHATS GOING ON...Same code.. different way of incrementing data i.e synchronization is at a different place..but results are very highly improved...





The Bank method is called by another method which runs 50 threads , so at a time 50 threads could enter this method to record Debit...
----------------------------------------------------------------------------------------------------------------------------------


ANSWER: Record is 135 millis for 5000 increments or 5000 calls to recordDebit()


Expected time was : 5000 * 2500 = 125000000 = 125 millis (WOW .. AS EXPECTED)

Please don't ask me why this code has been written this way..i know it goes and increment and does the same thing...but somehow when i measured it..
overall time or the accumulated time for both codes varied like in huge numbers...even though latter code is actually a superset of previous code..

HOW IS THERE SUCH A HUGE DIFFERENCE BETWEEN THE NUMBERS ???
COULD BE BECAUSE OF THE POINT OF SYNCHRONIZATION ???

Thank you..for going through all this..
[ September 27, 2008: Message edited by: Bear Bibeault ]
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18821
    
  40

HOW IS THERE SUCH A HUGE DIFFERENCE BETWEEN THE NUMBERS ???
COULD BE BECAUSE OF THE POINT OF SYNCHRONIZATION ???


Well, how would you test any speculations?

Is it due to the synchronizations? Maybe. What happens when you remove the synchronizations? (assuming it still works)

Is it due to the fact that you have 50 threads share one processor? Maybe. What happens when you drop the number of threads down to one?

Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

If I understand what is being called in each thread correctly then:

In the first example you can't increment while you are logging data since both the incrementing and the logging methods are synchronized. When you synchronize a method the lock is the object which the method belongs to (the 'this' object).

In the second example, since you are synchronizing the increment on a different object then the one doing the logging you can log and increment at the same time. Most of your wasted time, then is probably spent waiting for the logging to finish (which most likely needs to access a log file, and IO is much slower than anything else you are doing).


Steve
Anish Shah
Greenhorn

Joined: Sep 24, 2008
Posts: 20
In the first example you can't increment while you are logging data since both the incrementing and the logging methods are synchronized. When you synchronize a method the lock is the object which the method belongs to (the 'this' object).


to reply on this,

both logging and incrementing can happen together as both use differnt shared data.. Logging does not require and data from 1st method so it can exclusively...
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

Originally posted by Anish Shah:

both logging and incrementing can happen together as both use differnt shared data.. Logging does not require and data from 1st method so it can exclusively...


Correction, both the logging and incrementing should be able to happen together, as both use different shared data. But since you use method locking you are preventing them from doing so. When you synchronize methods you are ensuring that only ONE synchronized method of a class can run at a time. So the fix is to synchronize inside the method with different locks. Having different debit and record locks will ensure that only one thread can access these fields at a time, but will make sure that a debit action doesn't block a record action, and vice-versa. Example:

[ September 25, 2008: Message edited by: Steve Luke ]
Anish Shah
Greenhorn

Joined: Sep 24, 2008
Posts: 20
Thanks for the replies..

Shit.. i m so naive at this.. Please correct me on this if i am wrong..

You mean to say if there are 5 synchornized methods in a class in a multithreaded system.. then ony one of those method can execute at a time..
i wish this is wrong.. please give me a good idea on it..
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24184
    
  34

Originally posted by Anish Shah:

You mean to say if there are 5 synchornized methods in a class in a multithreaded system.. then ony one of those method can execute at a time..
i wish this is wrong.. please give me a good idea on it..


Only one of those methods may be executing at a time on a given object. If a class has five synchronized instance methods, and your create five instances of the class, then five threads could call any of the five methods on any of the five objects, all at once. But if there's only one object, and all five threads want to call a different synchronized method on that one object, then yes, they need to wait.


[Jess in Action][AskingGoodQuestions]
Anish Shah
Greenhorn

Joined: Sep 24, 2008
Posts: 20
Wow.. this is some awesomely new to me... so an object at a time can have only 1 synchronized method running unless and until it has multiple instances running...

Thanks a lot guys.. let me test it..
Thanks for all the replies.. will be back with the results soon..
Mark Waes
Greenhorn

Joined: Aug 06, 2008
Posts: 21
I've just been studying this, and my understanding is that if an instance of an obect is being accessed via a synchronised method, then any other syncronised method of that instance is also locked. Non-sycronised methods are not locked, however...
Anish Shah
Greenhorn

Joined: Sep 24, 2008
Posts: 20
Just was thinking about this whole synchronized waiting thing on the same object... Guys please tell me one thing.. say for example .. we are using the instance variable debit in 1st synchronized method and this same variable is used in another unsynchronized method where it is being just read.. so the read can happen on tihs instance variable without wait ??

Also, what would be the way out of this thing if we have multiple synchronized methods not using the same shared data in the same class i.e same instant..if we use synchronization within methods.would this help ??
how do we do this ??

Sorry if any of my question sound stupid to anyone.. I am just trying to learn something that i got to know very recently..
Thanks for all the replies..

Thank you..
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

Originally posted by Anish Shah:
Just was thinking about this whole synchronized waiting thing on the same object... Guys please tell me one thing.. say for example .. we are using the instance variable debit in 1st synchronized method and this same variable is used in another unsynchronized method where it is being just read.. so the read can happen on tihs instance variable without wait ??


If debit is a simple value like a primitive, then you would not need to synchonize to read it, unless you want to make sure that it is set before you read it. Take for example this:


If I call getDebit and the debit increment has not happened yet, I will get a zero, or whatever the pre-incrementing value was. This is fine and you don't risk any un-safe behavior. This is only true if you are only reading debit. If you need to change debit at all then you will need to synchronize. And if the debit is not a primitive or Immutable type then you should also synchronize reading (if it is a List for example, that you need to iterate over, or a custom object that has setter methods).

If you need more accuracy on the returned debit, that is, if one thread increments debit and you must have the latest value then you would want to synchronize getDebit on the same debitLock, so that if one thread is in the middle of incrementing the reading thread has to block until the increment is done, giving a more 'up-to-date' value.



Originally posted by Anish Shah:
Also, what would be the way out of this thing if we have multiple synchronized methods not using the same shared data in the same class i.e same instant..if we use synchronization within methods.would this help ??
how do we do this ??


My previous post shows you how to do this. You create individual Objects that do nothing but act as locks for the data they are meant to protect. You would not synchronize the method, but would use synchronized(lock) { } blocks like I have in my previous post. For example, I created a public final Object recordLock object. Only one thread at a time would be able to enter a synchronized(recordLock) { } block at a time. But another thread could enter a synchronized(debitLock) { } block while the first thread was in the synchronized(recordLock) { } block.

See my previous post for a full example.

Originally posted by Anish Shah:
Sorry if any of my question sound stupid to anyone.. I am just trying to learn something that i got to know very recently..
Thanks for all the replies..

Thank you..


None of your questions have been stupid. Please feel free to ask anymore that you might have. We will be happy to answer any we can. I hope I have been helping you understand this subject. It can be quite difficult to nail down, but is important especially with the growing multi-core computer world were multi-threading applications are under high demand...
Rahul Shilpakar
Ranch Hand

Joined: Aug 29, 2006
Posts: 132

Orginally posted by : Anish Shah

Expected time was : 5000 * 2500 = 125000000 = 125 millis



As you said in very first post, i just wanted to say that the 5000 * 2500 = 12500000. there will be 5 ZEROS in front of 125. You mentioned 6 ZEROS and which does not equal to 125 millis.

Notice this. Best luck if it does match your expected result.


Perform for today. Adapt for tomorrow.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Threads behaving weirdly