• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Doubt in exercise 9-2,K&B -Threads

 
Ranch Hand
Posts: 361
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


Im having trouble understanding synchronization in code. Im having trouble understanding how they are being able to synchronize on a common lock. because as I see it, there are 3 objects being created each contains a StringBuffer reference variable field, letter, which is assigned the StringBuffer variable sb. The synchronized block synchronizes on the letter variable which has been assigned the method local variable sb. I could understand this if sb was a static OR the reference variable, letter, was static. But neither of them is.
doesnt each object have its own local variable sb.? In main() when I say StringBuffer sb=new StringBuffer("A"); and after that create an object, doesnt each object then also have also have a new StringBuffer object sb contained within it? thereby having letter refer to their own copies of sb defeating the point of synchronization.
 
Ranch Hand
Posts: 54
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
that's a good question, not sure I have the answer, but I will try.

I think the original StringBuffer object is passed by value to the 3 InSync constructors. Because what you're passing by value is really a reference to the object, you end up getting 3 new references to the same object. Then inside the method, you get 3 more references, but they are also assigned the same object.

Total 7 references to the same object:
sb references "A"
the 3 method local vars named letter reference "A"
and the 3 this.letter fields reference "A"

So, my guess is this is why they are all locking on the same object. I bet this is also why you can only lock on objects and not primitives. Since if you pass a primitive around, you get a new copy of that primitive. Let me know if this is wrong, I find this topic difficult too.
 
Ranch Hand
Posts: 1274
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi all,

I find this topic difficult too.


I agree.

In your code only one SringBuffer object is instanciated with new. The three thread object don't have own StringBuffer objects, they only refer to the one.
That's why the method must be synchronized to that one and only object (letter).

Perhaps test this: change the synchronization from letter[/i} to [i]this, and the three threads will mix up. Probably - hardly anything is guarantied with threads ;-) - you'll have to add a Thread.sleep(10); line in your 100-times-for-loop to see the difference.


Yours,
Bu.
 
author
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yup... that's the correct answer.

Synchronization is based on objects -- not references. This means that even though the references are different, it works because they all point to the same object.

Another issue to be concerned about (which doesn't apply here), is the synchronization to the same reference that changes, also breaks because of this same rule. I have seen cases of classes synchronizing to an "error" object, right after they set it to a new error. In this case, same reference, but different object -- not really that useful.

So, my guess is this is why they are all locking on the same object. I bet this is also why you can only lock on objects and not primitives. Since if you pass a primitive around, you get a new copy of that primitive. Let me know if this is wrong, I find this topic difficult too.



Another issue is that a lock (monitor) is actually encapsulated into the Object class. You can't lock a primative, because there is nothing to lock.

Henry
[ September 07, 2006: Message edited by: Henry Wong ]
 
Amit Batra
Ranch Hand
Posts: 361
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I still a little unsure. Forgive me but, All this time I beleived that whenever I created an object, being that it had state(fields) and behaviours (methods) and that since this behaviour had local variables, I thought that each object would get a new StringBuffer Object sb within it too. I thought the exception to this rule was statics and string literals. Was I wrong to beleive this? In this case we are talking about the main() which has a StringBuffer sb object declared within it, is this why the situation is different here?
 
Dave Reinhardt
Ranch Hand
Posts: 54
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes, the difference is that the actual object is created in main, and it's that single object that is being passed around and refered to by multiple references.

When you see this:
StringBuffer sb = new StringBuffer("A");

It may help you to think of the thing on the left of the = as a reference and the thing on the right as the actual object. Since there's only one place in the code where you see "new" there's only one object being created. There are several instance references that are specific to the class instances, but they all point to this single object.

StringBuffer letter; // this is not a StringBuffer object, just a StringBuffer reference that will eventually refer to a StringBuffer object

I hope I'm understanding your question and this is helpful.
 
Ranch Hand
Posts: 138
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

I am tried the above code by removing the Synchronized block...

If the synchronized block is removed then each thread has to run it run method individually but it shows something different.
The output is like this...


AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ABBBABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BCCCCCCCCCCC



I did not understand the why it is showing 'A' character more than any 'B' and 'C' ?
reply
    Bookmark Topic Watch Topic
  • New Topic