zoukankan      html  css  js  c++  java
  • 6.显示锁Lock 和 线程通信Condition

    显示锁 Lock
    一、用于解决多线程 安全问题的方式:

      synchronized:   1.同步代码块      2.同步方法

      jdk1.5 后:第三种:同步锁Lock  (注意:同步(synchronized)是隐式的锁操作,而Lock对象是一个显示锁,需要通过lock() 方法上锁,必须通过unlock()方法进行释放锁(所以最好放到 finally 中))

      在 Java5.0 之前,协调共享对象的访问时可以使用的机制只有 synchronized 和 volatile

      在 Java5.0 后增加了一些 新的机制,但并不是一种替代内置锁的方法,而是当内置锁不适用时,作为一种可选择的高级功能

    /*ReentrantLock*/ 实现了 Lock 接口,并提供了 与 synchronized 相同的互斥性 和 内存可见性。,但相较于synchronized 提供了更高的处理锁的灵活性(使用Lock 加锁和解锁的时刻都是由我们控制的)

     1 public class TestLock {
     2     public static void main(String[] args) {
     3         TicketThread tt = new TicketThread();
     4         new Thread(tt, "1号窗口").start();
     5         new Thread(tt, "2号窗口").start();
     6         new Thread(tt, "3号窗口").start();
     7     }
     8 }
     9 
    10 class TicketThread implements Runnable {
    11     private int ticks = 100;
    12     // 创建锁
    13     private ReentrantLock lock = new ReentrantLock();
    14 
    15     @Override
    16     public void run() {
    17 
    18         while (true) {
    19             // synchronized (this) {
    20             lock.lock(); // 上锁
    21             try {
    22                 if (ticks > 0) {
    23                     try {
    24                         Thread.sleep(200);
    25                     } catch (InterruptedException e) {
    26                         // TODO Auto-generated catch block
    27                         e.printStackTrace();
    28                     }
    29                     System.out.println(Thread.currentThread().getName()
    30                             + "完成售票,余票为:" + --ticks);
    31                 }
    32 
    33             } finally {
    34                 lock.unlock();     //解锁,解锁操作必须有,所以最好就写在 fianlly 中
    35             }
    36         }
    37     }
    38 
    39 }

    线程通信Conidtion

      Condition 控制线程通信,Condition接口描述了 可能会与锁有关联的条件变量。这些变量在用法上与使用Object.wait 访问的隐式监听器类似,但提供了更强大的功能。

      需要特别指出的是,单个Lock 可能 与多个Condition 对象 关联。为了避免兼容性问题,Condition方法的名称与对应的Object版本中的不同

      之前使用的 是 wait notify notifyAll 完成线程之间的通信

      在 Condition 对象中,与wait、notify和 notifyAll 方法对应的分别是 await、singal 和 signalAll

      Condition的强大之处在于它可以为多个线程间建立不同的Condition,一个线程对饮一个Condition

      Condition 实例实质上被绑定到一个锁上。(即Condition使用的前提是 使用Lock同步锁)要为特定 Lock 实例 获得 Condition 实例,需使用其newCondition()     /* Condition condition = lock.newCondition();*/

    举例:线程按序交替

    编写一个程序,开启3个线程,这三个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出的结果必须按顺序显示,如  :  ABCABCABC...... 依次递归

    创建一个线程的标志num,用于判断按顺序排到了哪个线程执行,1

    创建三个Condition,绑定在一个Lock上,printA被加锁,线程A执行printA方法,先判断 这个线程的标志是否 等于 1(因为A是第一个线程),如果不等于1,说明现在还没排到这个线程执行,则阻塞线程1   Condition1.await,等待唤醒;如果等于1,就打印出A,将num置为2,说明轮到第二个线程执行了,则唤醒线程2Condition2.singal 

    以此类推,得到 printB 和 printC方法

      1 public class TestABCAlternate {
      2     public static void main(String[] args) {
      3         final AlternateThread at = new AlternateThread();
      4         
      5         //一般实际中,都是用这种匿名内部类的实现方式
      6         new Thread(new Runnable() {
      7             @Override
      8             public void run() {
      9                 for (int i = 0; i < 10; i++) {
     10                     at.printA();
     11                 }
     12 
     13             }
     14         }, "A").start();
     15         new Thread(new Runnable() {
     16             @Override
     17             public void run() {
     18                 for (int i = 0; i < 10; i++) {
     19                     at.printB();
     20                 }
     21             }
     22         }, "B").start();
     23         new Thread(new Runnable() {
     24             @Override
     25             public void run() {
     26                 for (int i = 0; i < 10; i++) {
     27                     at.printC();
     28                     System.out.println("---------------------");
     29                 }
     30             }
     31         }, "C").start();
     32     }
     33 }
     34 
     35 class AlternateThread {
     36     private int num = 1; // 创建线程的一个标志
     37 
     38     private ReentrantLock lock = new ReentrantLock();
     39     private Condition condition1 = lock.newCondition();
     40     private Condition condition2 = lock.newCondition();
     41     private Condition condition3 = lock.newCondition();
     42     public void printA() {
     43         lock.lock();
     44         try {
     45             // 1.判断
     46             if (num != 1) {
     47                 condition1.await();
     48             }
     49             // 2.打印
     50             System.out.println(Thread.currentThread().getName());
     51 
     52             // 3.唤醒
     53             num = 2;
     54             condition2.signal();
     55 
     56         } catch (Exception e) {
     57 
     58         } finally {
     59             lock.unlock();
     60         }
     61 
     62     }
     63 
     64     public void printB() {
     65         lock.lock();
     66         try {
     67             // 1.判断
     68             if (num != 2) {
     69                 condition2.await();
     70             }
     71             // 2.打印
     72             System.out.println(Thread.currentThread().getName());
     73 
     74             // 3.唤醒
     75             num = 3;
     76             condition3.signal();
     77 
     78         } catch (Exception e) {
     79 
     80         } finally {
     81             lock.unlock();
     82         }
     83 
     84     }
     85 
     86     public void printC() {
     87         lock.lock();
     88         try {
     89             // 1.判断
     90             if (num != 3) {
     91                 condition3.await();
     92             }
     93             // 2.打印
     94             System.out.println(Thread.currentThread().getName());
     95 
     96             // 3.唤醒
     97             num = 1;
     98             condition1.signal();
     99 
    100         } catch (Exception e) {
    101 
    102         } finally {
    103             lock.unlock();
    104         }
    105 
    106     }
    107 }
  • 相关阅读:
    (参考)爬虫5-爬取中国大学排名情况
    005_软件安装之_常用办公软件
    004_软件安装之_Altium Designer
    001_基础硬件电路_二极管
    添加QQ群
    024_STM32程序移植之_ESP8266_TCP
    020_C语言常用函数
    004——转载C#禁止改变窗体大小
    003转载----C#打开网页
    002_Python基础学习网站
  • 原文地址:https://www.cnblogs.com/xuzekun/p/7429073.html
Copyright © 2011-2022 走看看