マルチスレッド高同時プログラミング(2)--再入力ロックの紹介とカスタマイズができます。

10020 ワード

背景:
重入可能とは何ですか?再入力できるということは、あるスレッドはすでにロックを獲得していますが、再度ロックを取得することができます。ロックを再入力することができるのは、デッドロックを避けるためであり、javaでは、synchronizedとRentrant Lockは再入力可能です。
  //synchronized     
    private void test() {
        //        
        synchronized (this) {
            while (true) {
                //           
                synchronized (this) {
                    System.out.println("ReentrantLock!");
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

  //ReentrantLock    
    Lock lock = new ReentrantLock();
    private void test1() {
        lock.lock();
        try {
            test2();
        } finally {
            lock.unlock();
        }
    }
    private void test2() {
        lock.lock();
        try {
            System.out.println("ReentrantLock!");
        } finally {
            lock.unlock();
        }
    }
一.カスタムはロックを再入力できません。
再ロック不可とは、現在のスレッドがある方法を実行してロックを取得した場合、再びロックを取得しようとすると、ブロックされていないことになります。以下のスレッドがtest 1()を実行する方法はまずロックを取得し、次にtest 2()を実行する方法はtest 2()の論理を実行できなくなり、先にロックを解除しなければなりません。
//      
class Lock {
    //    
    private boolean isLocked = false;

    //   
    public synchronized void lock() {
        while (isLocked) {//    
            try {
                this.wait();//  
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        isLocked = true;//         
    }

    //   
    public synchronized void unLock() {
        isLocked = false;//        
        notify();//      
    }

}
============  ===========
    Lock lock = new Lock();

    public void test1() {
        lock.lock();
        test2();
        lock.unLock();
    }

    private void test2() {
        lock.lock();
        //...
        lock.unLock();
    }
二.カスタムでロックを再入力できます。
 プロセス:
  • は、ロック占有識別、記憶スレッド、スレッドロック保持数を定義する。
  • はロックを使用しています。現在のスレッドがメモリスレッドと等しくないかどうかを判断し、条件がログイン待ちに一致していない場合は、占有標識、記憶スレッドが現在のスレッド、スレッドロック数+1に変更されます。
  • リリースロック:現在のスレッドが記憶スレッドに等しいかどうかを判断し、条件が一致したらスレッドのロック数-1、スレッドのロック数=0の時に、占有標識を修正して、待ちスレッドを起動し、記憶スレッドをnullにセットする。
  • //     
    class ReLock{
        //    
        private boolean isLocked = false;
        private Thread lockedBy = null; //    
        private int holdCount = 0;
        //   
        public synchronized void lock() throws InterruptedException {
            Thread t = Thread.currentThread();
            while(isLocked && lockedBy != t) {
                wait();
            }
            isLocked = true;
            lockedBy = t;
            holdCount ++;
        }
        //   
        public synchronized void unlock() {
            if(Thread.currentThread() == lockedBy) {
                holdCount --;
                if(holdCount ==0) {
                    isLocked = false;
                    notify();
                    lockedBy = null;
                }        
            }        
        }
        public int getHoldCount() {
            return holdCount;
        }
    }
    ==============  ===============
    public class LockTest {
        ReLock lock = new ReLock();
        public void test1() throws InterruptedException {
            lock.lock();
            System.out.println(lock.getHoldCount());
            test2();
            lock.unlock();
            System.out.println(lock.getHoldCount());
        }
        //   
        public void test2() throws InterruptedException {
            lock.lock();
            System.out.println(lock.getHoldCount());
            //...................
            lock.unlock();
            System.out.println(lock.getHoldCount());
        }
        public static void main(String[] args) throws InterruptedException {
            LockTest lockTest= new LockTest();
            lockTest.test1();            
            Thread.sleep(1000);        
            System.out.println(lockTest.lock.getHoldCount());
        }
    
    }