Is the code that enters the synchronized block only if the thread is actually paused, an example of double check blocking?

If I remember correctly, there is a Sin in the Java thread, known as double-check locking.

It has been a while, but it is something like checking the value, then if it is true , it will go into the synchronized block and check it again. Since it was such a time, I cannot remember why this is an exact mistake. I remember that this is due to the Java specification, which allows implementations to somehow change the execution order of various statements (and because most of them usually didn't work). (The advantage was to minimize the need to go into synchronized blocks that are slow.)

I was browsing: http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html and came across:

A simple trick can be used to remove the synchronization that we have added to each iteration of the launch cycle. A synchronized block that has been replaced by a slightly more complex piece of code that enters the synchronized block only if the stream has really been suspended:

  if (threadSuspended) { synchronized(this) { while (threadSuspended) wait(); } } 

This is a bit like a double-check lock, but I feel it is wrong because it is from the official documentation.

Also the fact that this is a while seems to be a bit off. So what is the code of evil? Or not?

+4
source share
4 answers

No, this is not a double lock pattern, because when you lock a record, writing to shared variables is not performed.

The main problem that you may encounter is that threadSuspended changes from false to true may not be noticed as timely, due to caching or registration errors. Problems with register caching are the biggest problem (as a result, cache coherence ultimately solves, although it may take a few microseconds), and largely depends on the surrounding code and what the optimizer does.

If this is isolated code inside a function, you are unlikely to have a register cache problem. If threadSuspended is declared volatile , you will not have a problem either, as the optimizer will not register volatile cache files.

+1
source

Using the volatile keyword in the threadSuspended variable will give you the desired effect. The problem is that when multiple threads access the same variable, there may be streaming local caching of the variable. The volatile keyword ensures that this caching does not happen.

Here is a post explaining further.

EDIT:

Regarding time, since the purpose of the code is to wait until the thread is no longer suspended, I see no reason not to use while .

In addition, as mentioned in the commentary, the line below the snippet you pasted indicates volatile , and the full code snippet is a few lines below, declaring threadSuspended as volatile boolean .

+4
source

Two links about double lock checking:

  • Java Concurrency in Practice, 16.2.4. Double Check Lock
  • Effective Java Second Edition, Clause 71: Use Lazy Initialization Wisely
0
source

Regarding while - wait() allowed to return false - that is, without calling the notify() object on the object. This means that when wait() returns, it is probably, but not definitely, because someone installed threadSuspended and then called notify() . How do you protect this by rechecking threadSuspended , for which while exists.

0
source

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


All Articles