Hello. I study thread synchronization in Java, and, as I understood from the book, there are several ways to synchronize: through the synchronized , through the use of ReentrantLock and through the wait / notify .

  1. Did I select these methods correctly?
  2. Are these ways self-sufficient? Is it possible to use each of them without resorting to the others?
  3. The combination of these methods is impossible / undesirable / permissible / desirable?
  • one
    In addition to ReentrantLock in java.util.concurrent there are a lot of other interesting things for different occasions. synchronized is a simple, coarse solution unless you are interested in performance. wait/notify - very low-level operations, you need to understand how they work, but to use something more high-level. - Nofate

2 answers 2

Let the points:

  1. No, not right. A pair of wait()/notify() methods work only in a synchronized block. Therefore, they cannot be separated into a separate category. To delimit access to a shared resource, use:
    • synchronized block, or method.
    • some abstractions, in the form of a java.util.concurrent.Lock interface implementation, various semaphores, barriers, etc. Their types are abundantly represented in the java.util.concurrent package. However, no one forbids writing some kind of their own implementation.

2 and 3. The methods are self-sufficient and they can be used without mixing. But as a rule, in multi-threaded programs, several types of synchronization can occur. It all depends on the logic and conditions of use. I will give just a few examples:

  • if a resource is accessed less frequently and not many threads, then it will be more productive to use a lock based on CASs, since This allows you to rotate in a loop to avoid parking a thread, grab a resource, let it go and spend some CPU time.

  • if a resource has two modes: read and write, and relatively few threads write to it, then java.util.concurrent.ReadWriteLock used. This allows multiple reader threads to enter critical areas. But if a writer appears, readers wait for the reading to end.

    1. synchronized, wait, notify and notifyAll work in conjunction - these are primitives. ReentrantLock is a high-level construction and is implemented through primitives.
    2. You can create high-level constructions from primitives yourself, but you have to think through the architecture well.
    3. Typically, high-level constructions are used, rather than tart, but you can mix them if necessary.