Java happens earlier and synchronization

I have a slight disagreement with the fact that Java happens earlier and synchronization.

Imagine the following scenario:

Main theme

MyObject o = new MyObject(); // (0) synchronized (sharedMonitor) { // (1) add the object to a shared collection } // (2) spawn other threads 

Other topics

 MyObject o; synchronized (sharedMonitor) { // (3) retrieve the previously added object } // (4) actions to modify the object 

Note that the instance variables of MyObject are neither volatile nor final . MyObject methods do not use synchronization.

I understand that:

  • 1 occurs up to 3 , since there synchronization is on the same monitor, and the rest of the threads are generated only at 2 , which is performed after 1 .

  • Actions 4 do not guarantee that they will be visible later in the main thread unless there is additional synchronization for all threads, and the main thread is somehow synchronized after these actions.

Q: Is there any guarantee that actions at 0 will be visible, happen earlier, simultaneous access to 3 , or should I declare the variables as volatile ?


Now consider the following scenario:

Main theme

 MyObject o = new MyObject(); // (0) synchronized (sharedMonitor) { // (1) add the object to a shared collection } // (2) spawn other threads, and wait for their termination // (5) access the data stored in my object. 

Other topics

 MyObject o; synchronized (sharedMonitor) { // (3) retrieve the previously added object } o.lock(); // using ReentrantLock try { // (4) actions to modify the object } finally { o.unlock(); } 

I understand that:

  • 1 happens to 3 , as before.

  • Actions with 4 are displayed between other threads due to synchronization on a ReentrantLock stored in MyObject .

  • Actions 4 logically occur after 3 , but this does not happen - up to a ratio of 3 to 4 , as a result of synchronization on another monitor.

  • The above point would remain true even if after unlock synchronization was established on sharedMonitor 4 .

  • Actions 4 are not performed until access to 5 , although the main thread is waiting for the completion of the remaining tasks. This is because access to 5 is not synchronized with o.lock() , so the main thread can still see stale data.

Q: Do I understand correctly?

+4
source share
1 answer

Q: Is there any guarantee that actions at 0 will be visible, happen earlier, with simultaneous access at 3, or should I declare variables as mutable?

Yes, there is a guarantee. You do not need a synchronized block in the main thread because interdependence occurs when the threads start. From JLS 17.4.5: "A start () call is made on the thread - before any action on the running thread."

It also means that if you pass your o to the stream constructor, you won't need the synchronized block around (3).

Actions on (4) logically occur after (3), but do not happen - until the relationship from (3) to (4), as a result of synchronization on another monitor.

Yes and no. Logical order means that in the same thread, of course, there is a connection between them, even if it is a different monitor. The compiler cannot reorder 3 for 4, even if they deal with different monitors. The same would be true when accessing the volatile field.

With multiple threads, since (3) reads only an object, then there is no race condition. However, if (3) made changes to the object (as opposed to just reading it), then in another thread, these changes cannot be visible in (4). As you quote, and @StephenC echoes, JLS says that relationships occurring before this are guaranteed on only one monitor. JLS 17.4.5: "Unlocking on a monitor occurs before each subsequent lock on this monitor."

The point above would remain true, even if there was synchronization on sharedMonitor after unlocking (4).

See above.

Actions on (4) are not performed - until access on (5), although the main thread expects the remaining tasks to complete

No. As soon as the main thread calls thread.join() and it returns without interruption, the main thread is fully synchronized with the memory of the thread it joined. A connection is made between the connection of the streams and the stream. JLS 17.4.5: "All actions in a thread occur before any other thread successfully returns from connection () in that thread."

+9
source

Source: https://habr.com/ru/post/1487040/


All Articles