Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
The moose likes Threads and Synchronization and the fly likes Question regarding synchronized blocks/methods. Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Question regarding synchronized blocks/methods." Watch "Question regarding synchronized blocks/methods." New topic
Author

Question regarding synchronized blocks/methods.

Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1049
    
  15
Hi,

I have a question regarding synchronized blocks/methods and I'd appreciate if you could help me.

I get it that in the case of synchronized methods/blocks values loaded into temporary registers by a method are flushed back to main memory. But does this flushing back of register content into the main memory happen immediately after the block has changed the value loaded into the temporary register or does it happen only after the block ends?

Further, let us look at the following case. Let us assume that in this code, method1 can be called by multiple threads some of which may have the same SomeType object1 ( either same Class2 object or different Class2 objects that encapsulate same SomeType object ).




So is it possible that two threads that are accessing same Class2 object may have different SomeType object references/ different int a ( accessed via getters and getters only ) values even though they are accessed within a synchronized method? If that is true, then it means that synchronized blocks do not provide a guarantee that the values loaded into temporary registers ( for non atomic and non volatile members ) will be flushed back to memory immediately. Would that be right?


Thanks,
Chan.

Sorry- too many updates.
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1049
    
  15
Also I should add this.

Since single writes and single reads for references and primitives ( except doubles and long ) are atomic operations, I would not need to declare int a ( can be accessed only via getter ) as volatile. Right?

But again, if I also want to enforce that the value be stored and picked from main memory always, I may need to declare int a as volatile and for only this reason - not because I want to make the loading and writing atomic operations as they are atomic by default. Would that be right?
Maxim Karvonen
Ranch Hand

Joined: Jun 14, 2013
Posts: 104
    
  11
Important question. Which java version do you use? Java memory model changed drastically between JLS 2 and JLS 3. I will further speak only about JSL 3 (Java 1.5 and newer).

I get it that in the case of synchronized methods/blocks values loaded into temporary registers by a method are flushed back to main memory.

This sentence is absolutely incorrect. There is no main memory since JLS 3. All memory-effects are described in terms of happens-before relation. There may be no such "central" memory (some kind of NUMA architecture).

But does this flushing back of register content into the main memory happen immediately after the block has changed the value loaded into the temporary register or does it happen only after the block ends?

As I said before, there is no such memory. So, values may never been written into a main memory. And if no other threads performs synchonizations on a same object, then that threads may miss any changes made in that block.

To see a changes from a thread A in thread B following conditions should be true:
1. Thread A must synchronize sometime on an object a.
2. Thread B must synchronize on an object a.
3. No other threads enters a synchronized block on an object a.
Strictly speaking, this only disalllows to read "writer that happened before point 1" in a thread B. If there are some other unsynchronized changes (in thread C, for example), then thread B may see both writes (from A and C). Moreover, it may see there values "flipping" (write from C, write from A, write from C and write from A again) even there were only two writes (one in A and one in C).

So is it possible that two threads that are accessing same Class2 object may have different SomeType object references/ different int a ( accessed via getters and getters only ) values even though they are accessed within a synchronized method?

If there is no other unsyncrhonized access to instances of that classes, then no. And, of course, next thread executing method1 will see a value of a changed by a previous method invocation (see you first "Statement 2").

It is important to synchonize on a same Class2 object! If two threads syncrhonizes on two different objects (which shares same Class1 object) then you have no guarantees of visibility. Second "Statement 2" can see writes from "Statement 1" in both threads. Moreover, if you repeat tests you may see values "flipping"! Values not only can be written from a "main memory", they can "disappear" from that memory (revert to one of the previous values) and then return into it again when there is no proper synchronization!

Since single writes and single reads for references and primitives ( except doubles and long ) are atomic operations, I would not need to declare int a ( can be accessed only via getter ) as volatile. Right?

But again, if I also want to enforce that the value be stored and picked from main memory always, I may need to declare int a as volatile and for only this reason - not because I want to make the loading and writing atomic operations as they are atomic by default. Would that be right?


In general, you are correct. You use volatile for such field to guarantee visibility, not to ensure atomicity. Beware, that you may see "strange" values (default ones for example) if fields are not declared volatile and there are no other correct synchronization between threads. And if you access these fields in a synchronized block (always on a same object!) then there is no need to declare them as "volatile".

BTW. There is no difference in accessing a field via getter or directly unless getter is explicitly declared as synchronized method.
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1049
    
  15
Thanks a lot for your response.


Which java version do you use? Java memory model changed drastically between JLS 2 and JLS 3. I will further speak only about JSL 3 (Java 1.5 and newer).

I use Java 6. So I believe it must be JLS 3.

Ok, so the JLS defines commited changes and the rules for that in terms of a 'happens before' relationship now. I took a look into some JLS examples to understand what happens before meant - I liked the two examples I found ( to do with reordering of instructions ). I was not aware that instructions reordering could produce counter intuitive results and that such a thing also happens in Java ( I remember a mention of compiler optimizations or something similar in C or Pl/1 ) . Anyway coming back to the question - yes I mean the happens before too. I mean I'm interested in knowing what is a committed change -- by a committed change I mean something that the other threads can see.

So let me put my question this way.

Let us say I have two threads, thread1 and thread2 and a class2 object, say class2Object ( it has a Class1 object, say class1Object --> which has a SomeType Object, say someTypeObject and some int a). So if I have a method which is synchronized on Class2 object, and when thread1 has the lock of Class2Object, thread2 can still run methods on class1Object even though it does not have the lock of class2Object. Would that be correct? If yes, then the second thread can change SomeType object state and the value of a. Would that be right? So while thread1 is still executing within the synchronized context, the state of class2Object would have been changed by thread1. And the final result would be unpredictable. I'm not sure if this is right. Could you please confirm this?

If the above is possible and if I have to fix it, how would you fix it in the best possible way?

I think for int a part, like you said, we could make it volatile. But would it still be prone to inconsistent results because volatile variables do not ensure consistent results in the case of operations that can be decomposed into multiple operations, like say ++. So could the following sequence be a possibility even if I declared a as volatile.

Let us consider the synchronized method has an a++ instruction.

sequence 1: Thread1 reads a from memory - say it reads 5.
2 : Thread1 stores it in a temporary storage space.
3 : Thread1 adds 1 to the value in temporary storage space. It becomes 6.
4: Thread2 reads the content of a. It gets a 5 from the memory. ---> Is this read allowed is also one of my question.
5: Thread2 uses this value for some calculation - note this value was being processed by thread1 when thread2 read it. May be it writes this value back to a. This will now be visible to thread1. But thread1 does not read it.
6: Thread1 writes the result back. This result will now be visible to thread2 too cause a is volatile.

Could the above mentioned scenario still be a possibility with volatile variables-- especially sequence 4 part.

Also I got these questions while working on a post ( http://www.coderanch.com/t/614729/threads/java/Producer-Consumer-Thread ). So it will be a big help to me if someone could also help me with synchronizing the code in the mentioned post correctly or at least provide me a feedback on what they think is right or wrong in the way I have synchronized it.

Particularly these points -- should the content variable be a volatile variable for that particular case? Further do you think the synchronization is correctly done?

Actually I thought I'd try to find my own answers before I pestered Ranchers with more questions. But the more I thought about the intricacies of synchronization, the more I got confused. may be there is a little something I'm missing somewhere. Hence the questions.

Thanks in advance,
Chan.




Tony Docherty
Bartender

Joined: Aug 07, 2007
Posts: 2366
    
  50
Let us say I have two threads, thread1 and thread2 and a class2 object, say class2Object ( it has a Class1 object, say class1Object --> which has a SomeType Object, say someTypeObject and some int a). So if I have a method which is synchronized on Class2 object, and when thread1 has the lock of Class2Object, thread2 can still run methods on class1Object even though it does not have the lock of class2Object. Would that be correct?

I assume here we are only talking about methods in Class1 that are synchronized on the class1 object.
Yes, thread2 can run synchronized methods on class1Object because thread1 does not own class1Object's monitor lock.

If yes, then the second thread can change SomeType object state and the value of a. Would that be right?

Yes

So while thread1 is still executing within the synchronized context, the state of class2Object would have been changed by thread1.

Indirectly yes. The state of class1Object has been changed, but that's ok because no other thread owns it's monitor lock.

And the final result would be unpredictable. I'm not sure if this is right. Could you please confirm this?

That depends on what the code does with class1Object, but in all probability yes.

This is too complex for the Beginning Java forum so I'll move it to Threads and Synchronization forum.
Maxim Karvonen
Ranch Hand

Joined: Jun 14, 2013
Posts: 104
    
  11
Let us say I have two threads, thread1 and thread2 and a class2 object, say class2Object ... And the final result would be unpredictable. I'm not sure if this is right. Could you please confirm this?

Tony answered this part. Yes, result may be unpredictable.

Holding an object lock does not affect ability to call any unsynchronized methods on the same object. And it does not affect ability to call other methods on objects reachable from a "locked" object. More formally, object itself is never locked. Each object have a related "monitor" (which is not an object in a Java sense) which is locked or released.

If the above is possible and if I have to fix it, how would you fix it in the best possible way?

You should use proper synchronization and critical sections. And it should be done in all code that can use the variable. You cannot perform a "local" code change to ensure visibility/atomicity. To guarantee a proper synchronization you should introduce some convention like "to use following operations you should hold locks on objects A, B and C". In your example there may be a convention "to modify an object of a class Class1 thread must synchronize on that object first". So, first thread may also use two nested synchronized block (first on class2 and then on class1) to ensure that class1 instance is not modified.

As you see, maintaining such conventions may be a tough job. To deal with that usually an "abstraction" is used. All "atomic" operations of an instance are encapsulated in that instanance's methods. Class methods acquires necessary internal locks to perform operations, but that locks are not visible to outside classes. However, such incapsulation sometimeshile one thread operates on a resource, other thread can't acquire lock and should wait until that lock is released.

Volatile variables are not necessary in this case. Write visibility is guaranteed by a synchronized blocks. There is a happens-before edge between thread releasing a lock (either by waiting or by leaving synchronized block) and next lock acquisition. is not possible.

Let us consider the synchronized method has an a++ instruction. ... Could the above mentioned scenario still be a possibility with volatile variables-- especially sequence 4 part.

Yes, it is possible even with a volatile variables. Only explicit lock sections (either synchronized block or java.util.concurrent.*Lock) may make an execution block "atomic" and "critical section (one thread at a time may perform some operations)". You should choose an "lock" object for these operations and perform them in synchronized block.

Also I got these questions while working on a post ( http://www.coderanch.com/t/614729/threads/java/Producer-Consumer-Thread ). So it will be a big help to me if someone could also help me with synchronizing the code in the mentioned post correctly or at least provide me a feedback on what they think is right or wrong in the way I have synchronized it.

Particularly these points -- should the content variable be a volatile variable for that particular case? Further do you think the synchronization is correctly done?

As far as I see, your last code sample in that thread is OK (and Steve suggestion about termination will be fine, of course). You explicitly synchronizes on the resource object. And there are no other threads which performs unsynchronized access to the values. So, all threads access resource in a "synchronized" way. While one thread operates on a resource, other thread can't acquire lock and should wait until that lock is released.

Volatile variables are not necessary in this case. Write visibility is guaranteed by the synchronized blocks (on a same resource instance!). There is a happens-before edge between thread releasing a lock (either by waiting or by leaving synchronized block) and next lock acquisition which provides required guarantees.
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1049
    
  15
Thanks, guys. Very nice responses. I think I understand it a lot better now.

To guarantee a proper synchronization you should introduce some convention like "to use following operations you should hold locks on objects A, B and C". In your example there may be a convention "to modify an object of a class Class1 thread must synchronize on that object first". So, first thread may also use two nested synchronized block (first on class2 and then on class1) to ensure that class1 instance is not modified.


I had been wondering how do I get a lock on many objects. Wonder why nested synchronized blocks just didn't strike me. Thanks. Of course, like Steve mentioned in the earlier post, nested locks should be avoided. So if I will try to use them only if there'd be an absolute necessity to use them or may be there never is an absolute necessity in a nicely coded program and if you know how to make use of advanced concepts.

For now, I'm sorted. Thanks.

Chan.
Tony Docherty
Bartender

Joined: Aug 07, 2007
Posts: 2366
    
  50
I had been wondering how do I get a lock on many objects. Wonder why nested synchronized blocks just didn't strike me. Thanks. Of course, like Steve mentioned in the earlier post, nested locks should be avoided. So if I will try to use them only if there'd be an absolute necessity to use them or may be there never is an absolute necessity in a nicely coded program and if you know how to make use of advanced concepts.

The smart solution is either:
1. Write the code so that no other object can get a reference to class1Object, ie all access to class1Object is through an instance of Class2 so you can synchronize access easily.
2. Make Class1 immutable and then you don't need to worry about synchronization issues.
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1049
    
  15
Write the code so that no other object can get a reference to class1Object, ie all access to class1Object is through an instance of Class2 so you can synchronize access easily.


Such a simple, yet powerful technique. And I could make sure that even the main() method does not get class1Object reference directly..

Thanks.
Chan.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Question regarding synchronized blocks/methods.