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

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

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

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

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

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

 public class TestLock {
public static void main(String[] args) {
TicketThread tt = new TicketThread();
new Thread(tt, "1号窗口").start();
new Thread(tt, "2号窗口").start();
new Thread(tt, "3号窗口").start();
}
} class TicketThread implements Runnable {
private int ticks = 100;
// 创建锁
private ReentrantLock lock = new ReentrantLock(); @Override
public void run() { while (true) {
// synchronized (this) {
lock.lock(); // 上锁
try {
if (ticks > 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "完成售票,余票为:" + --ticks);
} } finally {
lock.unlock(); //解锁,解锁操作必须有,所以最好就写在 fianlly 中
}
}
} }

线程通信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方法

 public class TestABCAlternate {
public static void main(String[] args) {
final AlternateThread at = new AlternateThread(); //一般实际中,都是用这种匿名内部类的实现方式
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
at.printA();
} }
}, "A").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
at.printB();
}
}
}, "B").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
at.printC();
System.out.println("---------------------");
}
}
}, "C").start();
}
} class AlternateThread {
private int num = 1; // 创建线程的一个标志 private ReentrantLock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
public void printA() {
lock.lock();
try {
// 1.判断
if (num != 1) {
condition1.await();
}
// 2.打印
System.out.println(Thread.currentThread().getName()); // 3.唤醒
num = 2;
condition2.signal(); } catch (Exception e) { } finally {
lock.unlock();
} } public void printB() {
lock.lock();
try {
// 1.判断
if (num != 2) {
condition2.await();
}
// 2.打印
System.out.println(Thread.currentThread().getName()); // 3.唤醒
num = 3;
condition3.signal(); } catch (Exception e) { } finally {
lock.unlock();
} } public void printC() {
lock.lock();
try {
// 1.判断
if (num != 3) {
condition3.await();
}
// 2.打印
System.out.println(Thread.currentThread().getName()); // 3.唤醒
num = 1;
condition1.signal(); } catch (Exception e) { } finally {
lock.unlock();
} }
}

最新文章

  1. 一次kibana服务失败的排查过程
  2. [数学]内接多边形求pi
  3. javascript中function 函数递归的陷阱问题
  4. openldap sshkey & 用户自定义属性
  5. 使用X-UA-Compatible来设置IE8/IE9兼容模式
  6. expdp和impdp的用法
  7. Selenium+python+shell+crontab+firefox
  8. VLAN是什么
  9. linux 内存管理大图
  10. cf702D Road to Post Office
  11. DbUtility-查询DataTable
  12. 解决全站ie6下PNG图片不透明问题只要几行代码
  13. 如何导入外部的源码到eclipse中
  14. hive入门(一)、什么是hive
  15. MSIL实用指南-生成索引器
  16. Git 处理tag和branch的命令
  17. 我应该跟libuv说声对不起,我错怪了libuv(转)
  18. ES6 Promise 用法转载
  19. JAVA8 in Action:行为参数化,匿名类及lambda表达式的初步认知实例整理
  20. 怎么让table中的&lt;td&gt;内容向上对齐

热门文章

  1. 讲sql注入原理的 这篇不错(有空可以看看)
  2. 一秒 解决 ERROR 1044 (42000): Access denied for user &#39;&#39;@&#39;localhost&#39; to database &#39;mysql 问题
  3. python之socket编程(一)
  4. 【Leetcode_easy】784. Letter Case Permutation
  5. 添加tomcat8为服务
  6. 实现一个Promise
  7. linux中的pvmove,pvremove,pvs,pvscan
  8. jquery入口函数的测试
  9. [转帖]CentOS 8 都发布了,你还不会用 nftables?
  10. JVM -- 虚拟机中的对象