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 加锁和解锁的时刻都是由我们控制的)
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();
}
}
}
6.显示锁Lock 和 线程通信Condition的更多相关文章
- 显示锁lock
一.内置锁sync 和 显示锁lock概念 1.synv锁又叫内置锁,不能中断,拿不到无限等待即阻塞: java自带关键字: 隐式可重入: 重入锁:锁对应对象要多次调用对应方法,如递归 2. lock ...
- 扯扯python的多线程的同步锁 Lock RLock Semaphore Event Condition
我想大家都知道python的gil限制,记得刚玩python那会,知道了有pypy和Cpython这样的解释器,当时听说是很猛,也就意味肯定是突破了gil的限制,最后经过多方面测试才知道,还是那德行… ...
- 22.线程通信Condition
Condition 通过此对象可以与lock实现组合使用,为每个对象提供多个等待,实现多个阻塞队列. package dmeo9; import java.util.concurrent.lo ...
- Condition线程通信(七)
前言:对于线程通信,使用synchronized时使用wait.notify和notifyAll来实行线程通信.而使用Lock如何处理线程通信呢?答案就是本片的主角:Condition. 一.Cond ...
- 显式锁(二)Lock接口与显示锁介绍
一.显式锁简介 显式锁,这个叫法是相对于隐式锁synchronized而言的,加锁和解锁都要用户显式地控制.显示锁Lock是在Java5中添加到jdk的,同synchronized一样,这也是一 ...
- JAVA基础知识之多线程——线程通信
传统的线程通信 Object提供了三个方法wait(), notify(), notifyAll()在线程之间进行通信,以此来解决线程间执行顺序等问题. wait():释放当前线程的同步监视控制器,并 ...
- Java显式锁学习总结之六:Condition源码分析
概述 先来回顾一下java中的等待/通知机制 我们有时会遇到这样的场景:线程A执行到某个点的时候,因为某个条件condition不满足,需要线程A暂停:等到线程B修改了条件condition,使con ...
- Java 显示锁 之 队列同步器AQS(六)
1.简述 锁时用来控制多个线程访问共享资源的方式,一般情况下,一个锁能够防止多个线程同时访问共享资源.但是有些锁可以允许多个线程并发的访问共享资源,比如读写锁. 在Java 5.0之前,在协调对共享对 ...
- Java并发(基础知识)——显示锁和同步工具类
显示锁 Lock接口是Java ...
随机推荐
- Qt编写控件属性设计器2-拖曳控件
一.前言 上一篇文章把插件加载好了,并且把插件中的所有控件都显示到了列表框中,这次要做的就是实现拖曳控件的功能,用户选择一个控件拖曳到画布上,松开,在松开位置处自动实例化该控件,这个需要用到dropE ...
- (八)利用apache组件进行文件上传下载
一.文件上传 文件上传,即服务器端得到并处理用户上传的文件,这个文件存放在request里,也就是需要对request进行处理. 1.1 编写html文件 <!DOCTYPE html> ...
- Spring Boot使用监听器Listener
之前介绍了在Spring Boot中使用过滤器:https://www.cnblogs.com/zifeiy/p/9911056.html 接下来介绍使用监听器Listener. 下面是一个例子: p ...
- Spring 本地事务
主要原理: 事务的顶层接口: PlatformTransactionManager提供了3个方法,在申明式事务中这3个方法都是通过aop 调用的: 1.getTransaction: 进入相关需要被拦 ...
- 这一次,真正掌握composer
思维导图 composer是现代PHP的基石 现代高级编程语言,依赖管理工具是必不可少的.Java有Maven,Python有pip,Nodejs有npm, 而在composer出现之前,PHP只 ...
- 接着上次的python爬虫,今天进阶一哈,局部解析爬取网页数据
*解析网页数据的仓库 用Beatifulsoup基于lxml包lxml包基于html和xml的标记语言的解析包.可以去解析网页的内容,把我们想要的提取出来. 第一步.导入两个包,项目中必须包含beau ...
- CX ONE 不能全屏
兼容性 win7 以管理员方式运行 1. 打开CX-Programmer,选择“工具”——“选项”:2. 点击“通用”选项卡,选择“高级”:3. 勾选“当下一次启动CX-Programmer时不显示 ...
- Java实现回形数,只利用数组、循环和if-else语句
import java.util.Scanner; public class learn { public static void main(String[] args){ System.out.pr ...
- Netty学习笔记(三)——netty源码剖析
1.Netty启动源码剖析 启动类: public class NettyNioServer { public static void main(String[] args) throws Excep ...
- 用gcd库函数求最大公约数
如何直接调用库函数来求最大公约数呢? 1.首先看怎样求两个数的最大公约数 要注意gcd()前面是两个“_” !!! #include<bits/stdc++.h> using namesp ...