In multithreaded programming, multiple threads often access the same resource, so the resource that can be accessed by multiple threads at the same time is called critical resource.

The significance of designing synchronizer

  • Resources can be divided into thread-shared resources and thread-private resources according to the visibility between threads. Because threads execute processes that are uncontrollable, synchronization mechanisms are needed to ensure mutually exclusive access to mutable object states (shared resources).

How to solve the problem of thread concurrency safety?

  • Serialized access to critical resources is at the heart of concurrency solutions. Ensure that only one thread can access a critical resource at a time, also known as synchronous mutex access. Java provides two ways to implement mutually exclusive access: synchronized and Lock. The essence of a synchronizer is locking. The purpose of locking is to serialize access to critical resources, that is, only one thread can access critical resources at a time (synchronous mutex access), but there is a difference: When multiple threads execute a method, local variables inside that method are not critical resources because they are thread-private properties in each thread’s thread stack and do not cause thread-safety issues.

Detailed explanation of synchronized principle

! Synchronized and reentrantlock perform almost exactly the same in JDK1.5.

  • Synchronized built-in lock is an object lock (the lock is an object rather than a reference). The lock granularity is an object. It can be used to achieve mutually exclusive access to critical resources and is a reentrant lock. General locking mode:

    1. Synchronize instance method, lock is the current instance object 2. Synchronize class method, lock is the current class object 3Copy the code
  • Synchronized is based on the JVM built-in lock, through the internal object Monitor(Monitor lock), based on the entry and exit of Monitor object implementation method and code block synchronization, the implementation of Monitor lock depends on the underlying operating system Mutex lock (Mutex lock) implementation. It is a heavyweight lock with low performance. Of course, JVM built-in locks have made significant optimizations since version 1.5, such as:

    - Lock Coarsening Lock Elimination Lightweight Locking Biased Locking Adaptive Locking (Spinning) and other techniques to reduce the overhead of locking operations, and the concurrency performance of built-in locks has been nearly equal to that of Locks. The synchronized keyword is translated into bytecode and translated into monitorenter and Monitorexit at the start and end of the synchronized block logic code, respectively.Copy the code

The synchronized keyword is compiled into bytecode and translated into Monitorenter and Monitorexit

Each synchronization object has its own Monitor lock, as shown below:

  • Monitor Monitor lock

    • Any object has a Monitor associated with it, and when a Monitor is held, it is locked. Synchronized implementations in the JVM are based on entering and exiting Monitor objects to implement method synchronization and code block synchronization. Although the implementation details vary, they are implemented through pairs of MonitorEnter and MonitorExit directives.
    • Monitorenter: Each object is a monitor lock. The monitor is locked when it is occupied, and the thread attempts to acquire ownership of the Monitor when it executes the Monitorenter instruction as follows:
      • A. If the number of entries to monitor is 0, the thread enters monitor and sets the number of entries to 1. The thread is the owner of monitor.
      • B. If the thread already owns the monitor and just re-enters, the number of entries into the monitor is increased by 1;
      • C. If the monitor is occupied by another thread, the thread blocks until the number of monitor entries is 0, and then tries to acquire ownership of the monitor again.
    • Monitorexit: The thread executing monitoreXit must be the owner of the monitor to which objectref corresponds. When the instruction is executed, the number of monitor entries decreases by 1. If the number of monitor entries decreases by 1, the thread exits the monitor and is no longer the owner of the monitor. Other threads blocked by the monitor can try to take ownership of the monitor.
    • Monitorexit, the instruction appears twice, the first time releasing the lock for a normal exit from synchronization; The second time to release the lock for asynchronous exit is to ensure that the lock of the object must be released.