Why is it "synchronized" (new object ()) {} `no-op?

In the following code:

class A { private int number; public void a() { number = 5; } public void b() { while(number == 0) { // ... } } } 

If method b is called and then a new thread is launched that starts method a, then method b does not guarantee to ever see the change in number and therefore b never exit.

Of course, we could do number volatile to solve this problem. However, for academic reasons, suppose volatile not an option:

JSR-133 Frequently Asked Questions :

After exiting the synchronized block, we exit the monitor, which flushes the cache to the main memory , so that the entries made by this thread can be visible to other threads. Before we can enter a synchronized block, we will get a monitor that has the effect of invalidating the local processor cache so that the variables are reloaded from the main memory.

It seems like I just need both a and b to enter and exit any synchronized -Block in general, no matter which monitor they use. More precisely, it sounds like this:

 class A { private int number; public void a() { number = 5; synchronized(new Object()) {} } public void b() { while(number == 0) { // ... synchronized(new Object()) {} } } } 

... will fix the problem and ensure that b sees the change to a and therefore also ends.

However, the frequently asked questions also clearly state:

Another consequence is the following pattern, which some people use to force the memory barrier, does not work:

 synchronized (new Object()) {} 

This is actually non-op, and your compiler can completely remove it, because the compiler knows that no other thread will synchronize the same monitor. You must establish a connection between events and one thread in order to see the results of another.

Now this is confusing. I thought that a synchronized statement would cause a cache reset. Of course, it cannot clear the cache from main memory so that changes in main memory can only be displayed by threads that are synchronized on one monitor, especially since for volatile, which basically does the same, we don’t even need a monitor, or I am wrong there? So why is it non-op and does not cause b termination of the warranty?

+52
java multithreading java-memory-model
May 10 '16 at 15:08
source share
2 answers

Frequently asked questions do not constitute authority on this matter; JLS Section 17.4.4 defines synchronization - with relations that are transferred to relations-relations (17.4.5). The relevant paragraph indicates:

  • The unlock action on monitor m is synchronized with all subsequent lock actions on m (where the “subsequent” is determined in accordance with the synchronization order).

Since m here is a reference to new Object() and is never saved or published to any other thread, we can be sure that no other thread will get a lock on m after the lock in this block is blocked. In addition, since m is a new object, we can be sure that there were no actions that were previously unlocked. Therefore, we can be sure that no action is formally synchronized with this action.

Technically, you don’t even need to do a full cache flash to meet the JLS specification; this is more than JLS requires. A typical implementation does this because it is the simplest thing that hardware allows, but it happens "higher and lower," so to speak. In cases where leak analysis tells the optimizing compiler that we need even less, the compiler can do less. In your example, an analysis of the escape code can tell the compiler that the action has no effect (due to the reasoning above) and can be fully optimized.

+49
May 10 '16 at 15:16
source share

The following pattern, which some use for a forced memory barrier, does not work:

This does not guarantee the absence of an operation, but the specification allows it to be non-op. The specification only requires synchronization to establish the relationship between two streams when two streams are synchronized on the same object, but in fact it would be easier to implement a JVM where the identification of the object does not matter.

I thought synchronized-Statement would cause a cache reset

There is no "cache" in the Java language specification. This is a concept that exists only in the details of some (well, OK, almost all) hardware platforms and JVM implementations.

+20
May 10 '16 at 3:13
source share



All Articles