Category:Java多线程
Article From:https://www.cnblogs.com/scuwangjun/p/9124835.html

Java lock optimization”

Applications can cause many problems in concurrent environment. In general, we can solve the problem of multithread access to critical resources by locking. But locking will often become a bottleneck for the system, because locking and releasing locks will involve interaction with the operating system, and there will be a lot of performance problems. So this timeWaiting for lock based optimization is very important.

Generally, lock optimization can be done from two angles: optimization of single lock algorithm and subdivision of lock granularity.

1. single lock optimization

spin lock:

​ Non spin locks can be blocked without getting the lock, and then wake up to try to get the lock. The blocking and wakeup of JDK is based on the operation system, and it has the cost of system resources. A spin lock is a thread that keeps trying to get locks without stopping itself, so that it does not waste system resources.But it’s a waste of CPU resources. Most of the current JDK is first spin waiting. If the spin is not waiting for a period of time to get the lock, the current thread will be blocked.

lock elimination:

​ When JVM analyzes the code, it finds that a method is only accessed safely by a single thread, and this method is synchronous. Then JVM will remove the lock of this method.

the bottleneck of single lock Optimization:

​ The effect of a single lock optimization is like improving the processing ability of a single CPU, and finally a balance point is achieved due to the limitations of various aspects. After reaching this point, optimizing the optimization effect of a single lock on the high concurrent lock is getting lower and lower. So the effect of granularity of a lock will be obvious.If a lock – protected block is split into two locks to protect, the efficiency of the program can be raised to about 2 times, which is much more effective than a single lock optimization. The common lock granularity subdivision techniques are: Lock decomposition and lock segment.

2. subdivision lock granularity

The purpose of subdividing lock granularity is to reduce the probability of competing locks.

2.1 lock decomposition”

The core of the lock decomposition is the unrelated block of code. If a part of the code is unrelated to a lock in one method and a part of the code is related to the lock, it can reduce the return of the lock so that the lock operation block will be reduced and the possibility of lock competition will be reduced.

reduce the range of the lock

To reduce the range of the lock is to try to lock the lock as far as possible. Do not expand the range of the lock. Take a single example, and a large lock may lock the whole method.

class Singleton {
  private Singleton instance;

  private Singleton() {
  }

  // Lock the whole method
  public synchronized Singleton getInstance() {
    try {
      Thread.sleep(1000);  //do something
      if(null == instance)
        instance = new Singleton();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    return instance;
  }

}

After the optimization, only part of the code is locked:

class Singleton {
  private Singleton instance;

  private Singleton() {
  }

  public Singleton getInstance() {
    try {
      Thread.sleep(1000);  //do something
      // Only part of the code is locked
      synchronized(this) {
        if(null == instance)
          instance = new Singleton();
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    return instance;
  }
}

reduce the granularity of the lock

Reducing the granularity of a lock means that if a lock needs to protect multiple independent variables, a lock can be decomposed into multiple locks, and each lock is protected by a variable so that the lock conflict can be reduced. Look at the following examples:

class Demo{
  private Set<String> allUsers = new HashSet<String>();
  private Set<String> allComputers = new HashSet<String>();

  //A common lock
  public synchronized void addUser(String user){ 
    allUsers.add(user);
  }
  
  public synchronized void addComputer(String computer){
    allComputers.add(computer);
  }
}

After narrowing the size of the lock, a lock is split into several:

class Demo{
  private Set<String> allUsers = new HashSet<String>();
  private Set<String> allComputers = new HashSet<String>();
  
  //Break down into two locks
  public void addUser(String user){ 
    synchronized (allUsers){
      allUsers.add(user);
    }
  }
  
  public void addComputer(String computer){
    synchronized (allComputers){
      allComputers.add(computer);
    }
  }
}

The above method decomposes a lock into 2 locks. When using two threads, the efficiency of the program can be doubled.

2.2 lock section”

The size of the lock segment and the reduction lock is similar, that is, the granularity of the lock subdivision is more, for example, each location of an array is treated as a separate lock. Before JDK8, ConcurrentHashMap used the technology of lock segment, which divided the hash array into multiple Segment, each Seg.Ment stores the actual data. When accessing data, it only needs to lock the Segment where the data resides.

Reference resources:

JavaLock decomposition lock segment Technology: http://guochenglai.com/2016/06/04/java-concurrent4-java-subsection-decompose/

ConcurrentHashMapLock segment Technology: https://blog.csdn.net/yansong_8686/article/details/50664351

Link of this Article: Java lock optimization

Leave a Reply

Your email address will not be published. Required fields are marked *