Doubt that life failure can be avoided is discussed in Effective Java

I Link to Page 261 - 262 of Joshua Bloch Effective Java

// Properly synchronized cooperative thread termination public class StopThread { private static boolean stopRequested; private static synchronized void requestStop() { stopRequested = true; } private static synchronized boolean stopRequested() { return stopRequested; } public static void main(String[] args) throws InterruptedException { Thread backgroundThread = new Thread(new Runnable() { public void run() { int i = 0; while (!stopRequested()) i++; } }); backgroundThread.start(); TimeUnit.SECONDS.sleep(1); requestStop(); } } 

Note that both the write methods (requestStop) and the read-method (stop-Requested) are synchronized. It is not enough to synchronize only the recording method! In fact, synchronization has no effect if both read and write operations are synchronized.

The Joshua example syncs to this . However, I doubt that, should synchronized act on the same object? Say if I changed the code to

  private static void requestStop() { synchronized(other_static_final_object_monitor) { stopRequested = true; } } private static synchronized boolean stopRequested() { return stopRequested; } 

can this avoid giving up life?

That is, we know that capturing a monitor for the same object while reading / writing can avoid a malfunction (according to the example of Joshua Bloch). But what about capturing the monitor for different objects while reading / writing?

+4
source share
5 answers

I do not believe that this is guaranteed, although I would not be surprised if, in fact, everything was in order with all existing implementations. The Java Language Specification, Section 17.4.4, reads as follows:

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

I believe that all the security of reading / writing shared variables inside locks comes from this marker point in the specification - and this only indicates something about locking and the unlocking action on one monitor.

EDIT: even if this works for a single variable, you will not want to use it for multiple variables. If you update several variables while holding the monitor, and only read them while holding the monitor, you can make sure that you always read the consistent dataset: nothing will write to the Y variable before you read it, but after you read variable X. If you use different monitors for reading and writing, this consistency disappears: the values ​​can be changed at any time while you read them.

+2
source

Perhaps, but there are no guarantees, and this can be highly platform dependent. In your case, there is no real test for animation, so if the value is a few milliseconds, your application seems to be working correctly. The application will eventually terminate without any synchronized , and you may not see the difference.

The problem with memory consistency errors I saw examples where something can be correctly updated during the test 1 billion times, and then crash when another program is running on the system. This is why guaranteed behavior is more interesting.

+1
source

According to the Java Language Specification ,

"We say that reading r of a variable v is allowed to observe a record of w in v if, in a partial order of execution, the execution sequence:

  • r is not ordered to w (i.e., this is not the case when hb (r, w) and
  • there is no intermediate notation w 'on v (i.e. do not write w' on v such that hb (w, w ') and hb (w', r).

Unofficially, reading r is allowed to see the result of writing w, if this does not happen, before ordering to prevent this reading. "

This means that if there is no explicit synchronization action that causes several threads to alternate their actions in some predictable way (i.e. a good event occurs - up to the relationship defined for their actions), then the stream is allowed to see almost any value of the variable at any point where it was recorded.

If you synchronize on several different objects, it doesn’t happen - until the relationship between the reader and the author. This means that the read stream can continue to see whatever value it wants for the stopRequested variable, which can be either the first value forever, or the new value as soon as it is updated, or something delicious between them.

+1
source
This is theoretically wrong. Per lang spec v3, the background thread may not see the update.

In practice, this will work. A VM simply cannot be so smart as to optimize to such an extent. (In an older version of Java, which has the Threading specification differently, it is possible that your proposal is correct even in theory.)

In any case, do not do this.

0
source

If you use a different monitor, there is no synchronization. No other code requests a monitor for this or another_static_final_object_monitor.

Using a static object for synchronization is only useful if you want to synchronize between classes and within methods.

Also, NEVER use String as a lock / monitor. Always use something like this:

  static final Object LOCK = new Object(); 
-1
source

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


All Articles