Synchronized to the underlying

  • An early implementation of the JDK was heavyweight locking (requesting a lock from the operating system).
  • Hotspot implementation (lock upgrade)
    • The ID of the first accessed thread is recorded on the lock’s Markword, and the lock is not locked (biased locking).
    • If there is thread contention, upgrade to spin lock.
    • After the default spin is 10 times, it is upgraded to a heavyweight lock, and the thread that did not acquire the lock is queued.
    • Refer to ifeve.com/java-synchr…

B:

  • In Hotspot locks can only be upgraded, not degraded.
  • The spin lock only occupies CPU and does not access the operating system. To solve the lock problem in user mode, without going through the kernel mode, the efficiency of unlocking is high.
  • Use heavyweight locks for long execution times and many threads.

Synchronized optimization

  1. Lock refinement: The fewer statements in a synchronized code block, the better.
  2. Lock coarsening: If a method has many locks, locking the whole method will improve performance.
  3. The lock object is final.

volatile

  1. Ensure thread visibility

    • All threads share heap memory, and each thread has its own working memory. When a thread accesses data in the heap, it copies the data in the heap to the thread’s working memory. The change of this variable in the heap changes the data in the working memory. Changes to a thread heap variable are not immediately reflected to other threads, resulting in data being invisible between threads.
  2. Disallow instruction reordering

    • The CPU executes instructions concurrently to improve execution efficiency. With volatile, the CPU does not reorder.
      • DCL singleton
      package designPatterns;
      public class DCLSingleTon {
      
          private volatile static DCLSingleTon dclSingleTon;
      
          private DCLSingleTon(a) {}public static DCLSingleTon getInstance(a) {
              // The outer judgment can not be removed, which can significantly improve efficiency
              if (dclSingleTon == null) {
                  synchronized (DCLSingleTon.class) {
                      if (dclSingleTon == null) {
                          1. Allocate memory and assign default values to variables * 2. If an instruction reorder occurs, a 2 and 3 swap may occur. At this point, the dclSingleTon is no longer null, and the new thread will directly acquire the instance of the uninitialized member variable
                          dclSingleTon = newDCLSingleTon(); }}}returndclSingleTon; }}Copy the code
  3. Atomicity is not guaranteed

CAS (Compare And Swap)

  • cas(V, Expected, NewValue)

    if V == Expected
    	V = NewValue
    	otherwise try again or fail
    Copy the code
    • Cas in the Concurrent package is CPU primitive support and execution is not interrupted
  • ABA problem

    • The CAS operation of the current thread cannot tell whether the current V value has changed. For example, if you are very thirsty and find a glass full of water, drink it down and then refill your quilt with water. After you leave, the owner of the glass comes back and sees that the glass is still full. He can’t be sure that the glass has been refilled.
    • You can add the version number to solve the problem.
  • LongAdder compared to AtomicLong

    • Both use CAS operations to add or subtract.
    • No power is on the inside of the LongAdder is segmented lock.