zoukankan      html  css  js  c++  java
  • 架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock

    ReentrantLock

    有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级。

    this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决方案,后面jdk干脆就提供了一个Lock类。

    伪代码:

    Lock lock = new ReentrantLock();//新建一个lock

    Condition condition = lock.newCondition();//获取条件

    method1(){

      try{

        lock.lock();

        代码块;

        lock.unlock();

        后续代码块;

      }

    }

    method2(){

      try{

        lock.lock();

        代码块;

        lock.signal();

      }

    }

    单condition操作:

     1 import java.util.concurrent.locks.Condition;
     2 import java.util.concurrent.locks.Lock;
     3 import java.util.concurrent.locks.ReentrantLock;
     4 
     5 public class UseCondition {
     6 
     7     private Lock lock = new ReentrantLock();
     8     private Condition condition = lock.newCondition();
     9     
    10     public void method1(){
    11         try {
    12             lock.lock();
    13             System.out.println("当前线程:" + Thread.currentThread().getName() + "进入..");
    14             Thread.sleep(3000);
    15             System.out.println("当前线程:" + Thread.currentThread().getName() + "释放锁..");
    16             condition.await();    // Object wait
    17             System.out.println("当前线程:" + Thread.currentThread().getName() +"继续执行...");
    18         } catch (Exception e) {
    19             e.printStackTrace();
    20         } finally {
    21             lock.unlock();
    22         }
    23     }
    24     
    25     public void method2(){
    26         try {
    27             lock.lock();
    28             System.out.println("当前线程:" + Thread.currentThread().getName() + "进入..");
    29             Thread.sleep(3000);
    30             System.out.println("当前线程:" + Thread.currentThread().getName() + "发出唤醒..");
    31             condition.signal();        //Object notify
    32         } catch (Exception e) {
    33             e.printStackTrace();
    34         } finally {
    35             lock.unlock();
    36         }
    37     }
    38     
    39     public static void main(String[] args) {
    40         
    41         final UseCondition uc = new UseCondition();
    42         Thread t1 = new Thread(new Runnable() {
    43             @Override
    44             public void run() {
    45                 uc.method1();
    46             }
    47         }, "t1");
    48         Thread t2 = new Thread(new Runnable() {
    49             @Override
    50             public void run() {
    51                 uc.method2();
    52             }
    53         }, "t2");
    54         t1.start();
    55 
    56         t2.start();
    57     }
    58     
    59     
    60     
    61 }

    执行结果:

     
    解释:线程1调用method1方法,线程2调用同一对象的method2方法,线程1先启动,线程1获取锁,进入method1的代码块,线程2也启动了,单是线程2被锁定,直到线程1发出lock.unlock()了,线程1才将锁释放,这时线程2获取锁,执行method2的代码块,线程2发出lock.signal(); 线程1才继续执行后续代码块。

     多condition操作:

      1 import java.util.concurrent.locks.Condition;
      2 import java.util.concurrent.locks.ReentrantLock;
      3 
      4 public class UseManyCondition {
      5 
      6     private ReentrantLock lock = new ReentrantLock();
      7     private Condition c1 = lock.newCondition();
      8     private Condition c2 = lock.newCondition();
      9     
     10     public void m1(){
     11         try {
     12             lock.lock();
     13             System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m1等待..");
     14             c1.await();
     15             System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m1继续..");
     16         } catch (Exception e) {
     17             e.printStackTrace();
     18         } finally {
     19             lock.unlock();
     20         }
     21     }
     22     
     23     public void m2(){
     24         try {
     25             lock.lock();
     26             System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m2等待..");
     27             c1.await();
     28             System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m2继续..");
     29         } catch (Exception e) {
     30             e.printStackTrace();
     31         } finally {
     32             lock.unlock();
     33         }
     34     }
     35     
     36     public void m3(){
     37         try {
     38             lock.lock();
     39             System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m3等待..");
     40             c2.await();
     41             System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m3继续..");
     42         } catch (Exception e) {
     43             e.printStackTrace();
     44         } finally {
     45             lock.unlock();
     46         }
     47     }
     48     
     49     public void m4(){
     50         try {
     51             lock.lock();
     52             System.out.println("当前线程:" +Thread.currentThread().getName() + "唤醒..");
     53             c1.signalAll();
     54         } catch (Exception e) {
     55             e.printStackTrace();
     56         } finally {
     57             lock.unlock();
     58         }
     59     }
     60     
     61     public void m5(){
     62         try {
     63             lock.lock();
     64             System.out.println("当前线程:" +Thread.currentThread().getName() + "唤醒..");
     65             c2.signal();
     66         } catch (Exception e) {
     67             e.printStackTrace();
     68         } finally {
     69             lock.unlock();
     70         }
     71     }
     72     
     73     public static void main(String[] args) {
     74         
     75         
     76         final UseManyCondition umc = new UseManyCondition();
     77         Thread t1 = new Thread(new Runnable() {
     78             @Override
     79             public void run() {
     80                 umc.m1();
     81             }
     82         },"t1");
     83         Thread t2 = new Thread(new Runnable() {
     84             @Override
     85             public void run() {
     86                 umc.m2();
     87             }
     88         },"t2");
     89         Thread t3 = new Thread(new Runnable() {
     90             @Override
     91             public void run() {
     92                 umc.m3();
     93             }
     94         },"t3");
     95         Thread t4 = new Thread(new Runnable() {
     96             @Override
     97             public void run() {
     98                 umc.m4();
     99             }
    100         },"t4");
    101         Thread t5 = new Thread(new Runnable() {
    102             @Override
    103             public void run() {
    104                 umc.m5();
    105             }
    106         },"t5");
    107         
    108         t1.start();    // c1
    109         t2.start();    // c1
    110         t3.start();    // c2
    111         
    112 
    113         try {
    114             Thread.sleep(2000);
    115         } catch (InterruptedException e) {
    116             e.printStackTrace();
    117         }
    118 
    119         t4.start();    // c1
    120         try {
    121             Thread.sleep(2000);
    122         } catch (InterruptedException e) {
    123             e.printStackTrace();
    124         }
    125         t5.start();    // c2
    126         
    127     }
    128     
    129     
    130     
    131 }

    执行结果:

    解释:t1、t2线程都是用第一个condition c1,t3线程用第二个condition c2,t4线程发出c1.signalAll() 唤醒t1和t2线程,t5发出c2.signal()唤醒t3线程。

    ReentrantReadWriteLock

    读写分离锁,读读共享、写写互斥、读写互斥。

     1 import java.util.concurrent.locks.ReentrantReadWriteLock;
     2 import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
     3 import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
     4 
     5 public class UseReentrantReadWriteLock {
     6 
     7     private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
     8     private ReadLock readLock = rwLock.readLock();
     9     private WriteLock writeLock = rwLock.writeLock();
    10     
    11     public void read(){
    12         try {
    13             readLock.lock();
    14             System.out.println("当前线程:" + Thread.currentThread().getName() + "进入...");
    15             Thread.sleep(3000);
    16             System.out.println("当前线程:" + Thread.currentThread().getName() + "退出...");
    17         } catch (Exception e) {
    18             e.printStackTrace();
    19         } finally {
    20             readLock.unlock();
    21         }
    22     }
    23     
    24     public void write(){
    25         try {
    26             writeLock.lock();
    27             System.out.println("当前线程:" + Thread.currentThread().getName() + "进入...");
    28             Thread.sleep(3000);
    29             System.out.println("当前线程:" + Thread.currentThread().getName() + "退出...");
    30         } catch (Exception e) {
    31             e.printStackTrace();
    32         } finally {
    33             writeLock.unlock();
    34         }
    35     }
    36     
    37     public static void main(String[] args) {
    38         
    39         final UseReentrantReadWriteLock urrw = new UseReentrantReadWriteLock();
    40         
    41         Thread t1 = new Thread(new Runnable() {
    42             @Override
    43             public void run() {
    44                 urrw.read();
    45             }
    46         }, "t1");
    47         Thread t2 = new Thread(new Runnable() {
    48             @Override
    49             public void run() {
    50                 urrw.read();
    51             }
    52         }, "t2");
    53         Thread t3 = new Thread(new Runnable() {
    54             @Override
    55             public void run() {
    56                 urrw.write();
    57             }
    58         }, "t3");
    59         Thread t4 = new Thread(new Runnable() {
    60             @Override
    61             public void run() {
    62                 urrw.write();
    63             }
    64         }, "t4");        
    65         
    66         t1.start();
    67         t2.start();
    68         
    69 //        t1.start(); // R 
    70 //        t3.start(); // W
    71         
    72 //        t3.start();
    73 //        t4.start();
    74     }
    75 }

    解释:t1和t2都是读,是共享的,可同时获得readLock同时进入read方法执行。t1是读和t3是写,是互斥的,只有t1执行完t3才能执行。t3、t4都是写,是互斥的,只有等t3执行完t4才能继续。

  • 相关阅读:
    葡萄城报表介绍:多数据源报表
    葡萄城报表介绍:报表打印
    葡萄城报表介绍:财务报表分析
    葡萄城报表介绍:数据钻取
    用递归法计算斐波那契数列的第n项
    奋进
    //java递归调用输出一个目录下的所有子目录及文件名称 (最新增加)
    分享下通过java 读取目录及子目录下指定文件名的路径 并放到一个List数组里面返回遍历和写到文件里(同时将不会出现覆盖问题和重复读入问题)
    $_SERVER函数获取的内容解释
    mysql数据库忘记密码
  • 原文地址:https://www.cnblogs.com/sigm/p/6247346.html
Copyright © 2011-2022 走看看