A variety of multi-threaded lock

    In the study multithreading, we often hear reentrant lock / non-reentrant lock, lock fair / unfair lock, write lock them one by one and now we have the mystery.

Under the package hierarchy Lock
Under the package hierarchy Lock

      1. reentrant lock / non-reentrant lock: most are provided jdk reentrant lock, such as syncronized, reentrantLock are re-entrant, it represents a single (the same can be said that a) multiple thread may acquire the lock If a single thread to get the lock is not released, you get another, is to get re-entry lock, can not get the non-reentrant lock.

 public static void main(String[] args) {
        //KodyLock lock = new KodyLock ();
        Lock lock = new ReentrantLock ();
        lock.lock ();
        System.out.println ("获得锁");
        lock.lock ();
        System.out.println ("再次获得锁");
    }

        As can be found ReentranLock be reentrant, and that non-reentrant lock it? Here is realized a simple non-reentrant lock

public class NCrLock {

    boolean isLock = false;

    public synchronized void  lock() throws InterruptedException{
        while (isLock){
            wait ();
        }
        isLock = true;
    }

    public synchronized void unlock(){
        isLock = false;
        notify ();
    }

    public static void main(String[] args) throws InterruptedException{
        NCrLock nCrLock = new NCrLock ();
        nCrLock.lock ();
        System.out.println ("获得锁");
        nCrLock.lock ();
        System.out.println ("再次获得锁");
    }

}

       2. Read-Write Lock: We know ReentrantLock an exclusive lock, allowing only one thread to access the same time, while ReentrantReadWriteLock allows multiple threads simultaneously read access, but does not allow read and write thread thread, the writer thread and write threads access, in practice, most of the shared data (cache) access is read much more than write it this time ReentrantReadWrite it locks provide better concurrency and throughput than rows.

 public static void main(String[] args) {
        ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock ();
        new Thread (() -> {
            reentrantReadWriteLock.readLock ().lock ();
            long startTime = System.currentTimeMillis ();
            while (System.currentTimeMillis () - startTime < 5){
                //记录5ms内 读线程做的事情
                System.out.println (Thread.currentThread ().getName () + ":正在进行读操作" );
            }
            reentrantReadWriteLock.readLock ().unlock ();
        },"读锁线程").start ();

        new Thread (() -> {
            reentrantReadWriteLock.readLock ().lock ();
            long startTime = System.currentTimeMillis ();
            while (System.currentTimeMillis () - startTime < 5){
                //记录5ms内 读线程做的事情
                System.out.println (Thread.currentThread ().getName () + ":正在进行读操作" );
            }
            reentrantReadWriteLock.readLock ().unlock ();
        },"读锁线程2").start ();


    }

Two threads console print information read as follows: try more than once because of possible scheduling switch cpu time difference which led to first perform a thread

读锁线程2:正在进行读操作
读锁线程:正在进行读操作
读锁线程2:正在进行读操作
读锁线程2:正在进行读操作
........

Read and write threads into the thread console print information is as follows:

读锁线程:正在进行读操作
读锁线程:正在进行读操作
读锁线程:正在进行读操作
写锁线程2:正在进行读操作
写锁线程2:正在进行读操作
写锁线程2:正在进行读操作
写锁线程2:正在进行读操作
.......

    3. Fair Fair locking and non-locking: java comes syncronized keywords in advance, and the method can ReentrantLock code block or lock, which locks the former only non-default non-fair fair locks, fair and unfair lock locks are based on a doubly linked list maintained by an internal lock, node node values ​​in the table is the current lock request each thread. Lock is fair value from the first team every turn, they are able to acquire the lock to ensure sequential, rather than lock fair is an opportunity to try to steal the lock, the lock may lead to demand and not grab a thread.

      So in summary at it is this:

  1. Lock fair order to obtain the lock is locked in order to allocate, namely, FIFO FIFO, non-equity and equity-locking lock is that it is not the same as random acquire the lock, not necessarily the first to get a lock, this approach may cause thread can not get a lock.

      Unfair lock: CAS-based attempts to state (number lock) from 0 to 1, if successful, set an exclusive lock to set the current thread to thread, if you set the number of failures will acquire a lock in:

  1. If the number of locks to zero-based CAS try to state from 0 to 1, if successful, set an exclusive lock to set the current thread to thread
  2. If the number of locks is not 0 or above attempt fails, the current view is not an exclusive lock locks the thread, then the number is +1 if the current thread lock, if not then the thread is encapsulated within a Node, and added to the waiting queue, waiting to be awakened before its thread a node

   Fair locks: one lock to get the number of

  1. If the number of locks to zero, if the current thread is waiting for the head of the queue node, based CAS try to state which is set from 0 to a 1, then the current set of threads to the success of an exclusive lock thread
  2. If the number of locks is not 0, or the current thread is not waiting for the head node queue or above attempt failed, view the current thread is not already an exclusive lock thread, then the number is +1 if the current lock, if not then the thread is enclosed within a Node, and added to the waiting queue, waiting to be preceded by a wake-up thread.
  public static void main(String[] args) throws InterruptedException{
        Lock lock = new ReentrantLock (false);
        //分别依次启动5个线程,观察它的执行情况
        IntStream.range (0,5).forEach (value -> {
            new Thread (() -> {
                System.out.println (Thread.currentThread ().getName () + "线程开始运行");
                lock.lock ();
                System.out.println (Thread.currentThread ().getName () + "拿到锁");
                lock.unlock ();
            },String.valueOf (value)).start ();
        });
    }

It can be seen order to get a thread lock to sequentially execute threads 0,1,3,4,2 0,1,4,3,2 obviously disordered

0线程开始运行
1线程开始运行
0拿到锁
3线程开始运行
1拿到锁
4线程开始运行
4拿到锁
2线程开始运行
3拿到锁
2拿到锁

Implementation of the fair changed the lock, the thread order to get a lock for the execution of the order 0,1,2,3,4 process is consistent with the order of 0,1,2,3,4 thread lock to get the order of thread execution, of course, the order of the lock get here is not all of the order of 0-4, the switching depends on the scheduling of who cpu.

public static void main(String[] args) throws InterruptedException{
        Lock lock = new ReentrantLock (true);
        //分别依次启动5个线程,观察它的执行情况
        IntStream.range (0,5).forEach (value -> {
            new Thread (() -> {
                System.out.println (Thread.currentThread ().getName () + "线程开始运行");
                lock.lock ();
                System.out.println (Thread.currentThread ().getName () + "拿到锁");
                lock.unlock ();
            },String.valueOf (value)).start ();
        });
    }
0线程开始运行
0拿到锁
1线程开始运行
1拿到锁
2线程开始运行
2拿到锁
3线程开始运行
3拿到锁
4线程开始运行
4拿到锁

 

 

 

Published 73 original articles · won praise 18 · views 10000 +

Guess you like

Origin blog.csdn.net/qq_40826106/article/details/101704900