00103_死锁、Lock接口、等待唤醒机制
1、死锁
(1)同步锁使用的弊端:当线程任务中出现了多个同步(多个锁)时,如果同步中嵌套了其他的同步。这时容易引发一种现象:程序出现无限等待,这种现象我们称为死锁。这种情况能避免就避免掉;
- synchronzied(A锁){
- synchronized(B锁){
- }
- }
(2)代码演示
①定义锁对象
- public class MyLock {
- public static final Object lockA = new Object();
- public static final Object lockB = new Object();
- }
②线程任务类
- import java.util.Random;
- public class ThreadTask implements Runnable {
- int x = new Random().nextInt(1);// 0,1
- // 指定线程要执行的任务代码
- @Override
- public void run() {
- while (true) {
- if (x % 2 == 0) {
- // 情况一
- synchronized (MyLock.lockA) {
- System.out.println("if-LockA");
- synchronized (MyLock.lockB) {
- System.out.println("if-LockB");
- System.out.println("if大口吃肉");
- }
- }
- } else {
- // 情况二
- synchronized (MyLock.lockB) {
- System.out.println("else-LockB");
- synchronized (MyLock.lockA) {
- System.out.println("else-LockA");
- System.out.println("else大口吃肉");
- }
- }
- }
- x++;
- }
- }
- }
③测试类
- public class ThreadDemo {
- public static void main(String[] args) {
- // 创建线程任务类对象
- ThreadTask task = new ThreadTask();
- // 创建两个线程
- Thread t1 = new Thread(task);
- Thread t2 = new Thread(task);
- // 启动线程
- t1.start();
- t2.start();
- }
- }
2、Lock接口
(1)Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作;
(2)Lock提供了一个更加面对对象的锁,在该锁中提供了更多的操作锁的功能;
(3)我们使用Lock接口,以及其中的lock()方法和unlock()方法替代同步,对卖票案例中Ticket类进行如下代码修改:
- public class Ticket implements Runnable {
- //共100票
- int ticket = 100;
- //创建Lock锁对象
- Lock ck = new ReentrantLock();
- @Override
- public void run() {
- //模拟卖票
- while(true){
- //synchronized (lock){
- ck.lock();
- if (ticket > 0) {
- //模拟选坐的操作
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticket--);
- }
- ck.unlock();
- //}
- }
- }
- }
3、等待唤醒机制
(1)线程之间的通信:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同;
(2)通过一定的手段使各个线程能有效的利用资源。而这种手段即—— 等待唤醒机制;
(3)等待唤醒机制所涉及到的方法:
①wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中;
②notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的;
③notifyAll(): 唤醒全部:可以将线程池中的所有wait() 线程都唤醒。
(4)其实,所谓唤醒的意思就是让线程池中的线程具备执行资格;
(5)这些方法都是在同步中才有效,同时这些方法在使用时必须标明所属锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程;
(6)仔细查看JavaAPI之后,发现这些方法 并不定义在 Thread中,也没定义在Runnable接口中,却被定义在了Object类中,为什么这些操作线程的方法定义在Object类中?
因为这些方法在使用时,必须要标明所属的锁,而锁又可以是任意对象。能被任意对象调用的方法一定定义在Object类中;
(7)模拟等待唤醒机制的实现,代码案例:
①模拟资源类
- public class Resource {
- private String name;
- private String sex;
- private boolean flag = false;
- public synchronized void set(String name, String sex) {
- if (flag)
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- // 设置成员变量
- this.name = name;
- this.sex = sex;
- // 设置之后,Resource中有值,将标记该为 true ,
- flag = true;
- // 唤醒output
- this.notify();
- }
- public synchronized void out() {
- if (!flag)
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- // 输出线程将数据输出
- System.out.println("姓名: " + name + ",性别: " + sex);
- // 改变标记,以便输入线程输入数据
- flag = false;
- // 唤醒input,进行数据输入
- this.notify();
- }
- }
②输入线程人任务类
- public class Input implements Runnable {
- private Resource r;
- public Input(Resource r) {
- this.r = r;
- }
- @Override
- public void run() {
- int count = 0;
- while (true) {
- if (count == 0) {
- r.set("小明", "男生");
- } else {
- r.set("小花", "女生");
- }
- // 在两个数据之间进行切换
- count = (count + 1) % 2;
- }
- }
- }
③输出线程任务类
- public class Output implements Runnable {
- private Resource r;
- public Output(Resource r) {
- this.r = r;
- }
- @Override
- public void run() {
- while (true) {
- r.out();
- }
- }
- }
④测试类
- public class ResourceDemo {
- public static void main(String[] args) {
- // 资源对象
- Resource r = new Resource();
- // 任务对象
- Input in = new Input(r);
- Output out = new Output(r);
- // 线程对象
- Thread t1 = new Thread(in);
- Thread t2 = new Thread(out);
- // 开启线程
- t1.start();
- t2.start();
- }
- }
00103_死锁、Lock接口、等待唤醒机制的更多相关文章
- java多线程(死锁,lock接口,等待唤醒机制)
一.Lock接口 常用方法 Lock提供了一个更加面对对象的锁,在该锁中提供了更多的操作锁的功能. 使用Lock接口,以及其中的lock()方法和unlock()方法替代同步,对电影院卖票案例中Tic ...
- 死锁、Lock锁、等待唤醒机制、线程组、线程池、定时器、单例设计模式_DAY24
1:线程(理解) (1)死锁 概念: 同步中,多个线程使用多把锁之间存在等待的现象. 原因分析: a.线程1将锁1锁住,线程2将锁2锁住,而线程1要继续执行锁2中的代码,线程2要继续执行锁1中的代码, ...
- java ->多线程_线程同步、死锁、等待唤醒机制
线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. l 我们通过一个案例,演示线 ...
- 多线程之间的通信(等待唤醒机制、Lock 及其它线程的方法)
一.多线程之间的通信. 就是多个线程在操作同一份数据, 但是操作的方法不同. 如: 对于同一个存储块,其中有两个存储位:name sex, 现有两个线程,一个向其中存放数据,一个打印其中的数据. ...
- JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制
JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是clas ...
- “全栈2019”Java多线程第三十二章:显式锁Lock等待唤醒机制详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Java多线程02(线程安全、线程同步、等待唤醒机制)
Java多线程2(线程安全.线程同步.等待唤醒机制.单例设计模式) 1.线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量 ...
- java基础(27):线程安全、线程同步、等待唤醒机制
1. 多线程 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. 我们通过一个案例,演示线程 ...
- java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)
*java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时 ...
随机推荐
- hiho week 38 P1 : 二分·二分答案
P1 : 二分·二分答案 Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB 描述 在上一回和上上回里我们知道Nettle在玩&l ...
- 使用UltraEdit配置多行注释和取消多行注释
UltraEdit功能强大,使用方便,成为软件开发者必备的文档和代码编辑工具.有很多人也直接用它来写代码,如C/Java,脚本如:Perl/Tcl/JavaScript 等. 如果用来写代码,有一个不 ...
- Vijos——T1626 爱在心中
https://vijos.org/p/1626 描述 “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our H ...
- 13.2 UPDATE
13.2 UPDATE正在更新内容.请稍后
- Zabbix + Grafana
Grafana 简介 Grafana自身并不存储数据,数据从其它地方获取.需要配置数据源 Grafana支持从Zabbix中获取数据 Grafana优化了图形的展现,可以用来做监控大屏 Grafana ...
- idea配置spark运行模式
1. 配置运行参数: Menu -> Run -> Edit Configurations -> 选择 + -> Application -Dspark.master=lo ...
- 源码安装 ipython
https://blog.csdn.net/huobanjishijian/article/details/51470898
- 【Codeforces Round #428 (Div. 2) B】Game of the Rows
[Link]:http://codeforces.com/contest/839/problem/B [Description] 给你n排的如题目所示的位置; 同一排中(1,2) 算相邻; (3,4) ...
- FZU 1962 新击鼓传花游戏
新击鼓传花游戏 Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on FZU. Original ID: 19 ...
- js08--函数1
函数当成类看当成匿名对象看,都是跟java吻合的,只有当成函数看(函数自己可以执行)跟java区别在这里. function fact(){} var F = fact ; 函数名是函数对象的地址,是 ...