1、死锁

  (1)同步锁使用的弊端:当线程任务中出现了多个同步(多个锁)时,如果同步中嵌套了其他的同步。这时容易引发一种现象:程序出现无限等待,这种现象我们称为死锁。这种情况能避免就避免掉;

  1. synchronzied(A锁){
  2. synchronized(B锁){
  3.  
  4. }
  5. }

  (2)代码演示

    ①定义锁对象

  1. public class MyLock {
  2. public static final Object lockA = new Object();
  3. public static final Object lockB = new Object();
  4. }

    ②线程任务类

  1. import java.util.Random;
  2.  
  3. public class ThreadTask implements Runnable {
  4. int x = new Random().nextInt(1);// 0,1
  5.  
  6. // 指定线程要执行的任务代码
  7. @Override
  8. public void run() {
  9. while (true) {
  10. if (x % 2 == 0) {
  11. // 情况一
  12. synchronized (MyLock.lockA) {
  13. System.out.println("if-LockA");
  14. synchronized (MyLock.lockB) {
  15. System.out.println("if-LockB");
  16. System.out.println("if大口吃肉");
  17. }
  18. }
  19. } else {
  20. // 情况二
  21. synchronized (MyLock.lockB) {
  22. System.out.println("else-LockB");
  23. synchronized (MyLock.lockA) {
  24. System.out.println("else-LockA");
  25. System.out.println("else大口吃肉");
  26. }
  27. }
  28. }
  29. x++;
  30. }
  31. }
  32. }

    ③测试类

  1. public class ThreadDemo {
  2. public static void main(String[] args) {
  3. // 创建线程任务类对象
  4. ThreadTask task = new ThreadTask();
  5. // 创建两个线程
  6. Thread t1 = new Thread(task);
  7. Thread t2 = new Thread(task);
  8. // 启动线程
  9. t1.start();
  10. t2.start();
  11. }
  12. }

2、Lock接口

  (1)Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作;

  (2)Lock提供了一个更加面对对象的锁,在该锁中提供了更多的操作锁的功能;

  (3)我们使用Lock接口,以及其中的lock()方法和unlock()方法替代同步,对卖票案例中Ticket类进行如下代码修改:

  1. public class Ticket implements Runnable {
  2. //共100票
  3. int ticket = 100;
  4.  
  5. //创建Lock锁对象
  6. Lock ck = new ReentrantLock();
  7.  
  8. @Override
  9. public void run() {
  10. //模拟卖票
  11. while(true){
  12. //synchronized (lock){
  13. ck.lock();
  14. if (ticket > 0) {
  15. //模拟选坐的操作
  16. try {
  17. Thread.sleep(10);
  18. } catch (InterruptedException e) {
  19. e.printStackTrace();
  20. }
  21. System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticket--);
  22. }
  23. ck.unlock();
  24. //}
  25. }
  26. }
  27. }

3、等待唤醒机制

  (1)线程之间的通信:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同;

  (2)通过一定的手段使各个线程能有效的利用资源。而这种手段即—— 等待唤醒机制;

  (3)等待唤醒机制所涉及到的方法:

    ①wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中;

    ②notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的;

    ③notifyAll(): 唤醒全部:可以将线程池中的所有wait() 线程都唤醒。

  (4)其实,所谓唤醒的意思就是让线程池中的线程具备执行资格;

  (5)这些方法都是在同步中才有效,同时这些方法在使用时必须标明所属锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程;

  (6)仔细查看JavaAPI之后,发现这些方法 并不定义在 Thread中,也没定义在Runnable接口中,却被定义在了Object类中,为什么这些操作线程的方法定义在Object类中?

  因为这些方法在使用时,必须要标明所属的锁,而锁又可以是任意对象。能被任意对象调用的方法一定定义在Object类中;

  (7)模拟等待唤醒机制的实现,代码案例:

    ①模拟资源类

  1. public class Resource {
  2. private String name;
  3. private String sex;
  4. private boolean flag = false;
  5.  
  6. public synchronized void set(String name, String sex) {
  7. if (flag)
  8. try {
  9. wait();
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. }
  13. // 设置成员变量
  14. this.name = name;
  15. this.sex = sex;
  16. // 设置之后,Resource中有值,将标记该为 true ,
  17. flag = true;
  18. // 唤醒output
  19. this.notify();
  20. }
  21.  
  22. public synchronized void out() {
  23. if (!flag)
  24. try {
  25. wait();
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. }
  29. // 输出线程将数据输出
  30. System.out.println("姓名: " + name + ",性别: " + sex);
  31. // 改变标记,以便输入线程输入数据
  32. flag = false;
  33. // 唤醒input,进行数据输入
  34. this.notify();
  35. }
  36. }

    ②输入线程人任务类

  1. public class Input implements Runnable {
  2. private Resource r;
  3.  
  4. public Input(Resource r) {
  5. this.r = r;
  6. }
  7.  
  8. @Override
  9. public void run() {
  10. int count = 0;
  11. while (true) {
  12. if (count == 0) {
  13. r.set("小明", "男生");
  14. } else {
  15. r.set("小花", "女生");
  16. }
  17. // 在两个数据之间进行切换
  18. count = (count + 1) % 2;
  19. }
  20. }
  21. }

    ③输出线程任务类

  1. public class Output implements Runnable {
  2. private Resource r;
  3.  
  4. public Output(Resource r) {
  5. this.r = r;
  6. }
  7.  
  8. @Override
  9. public void run() {
  10. while (true) {
  11. r.out();
  12. }
  13. }
  14. }

    ④测试类

  1. public class ResourceDemo {
  2. public static void main(String[] args) {
  3. // 资源对象
  4. Resource r = new Resource();
  5. // 任务对象
  6. Input in = new Input(r);
  7. Output out = new Output(r);
  8. // 线程对象
  9. Thread t1 = new Thread(in);
  10. Thread t2 = new Thread(out);
  11. // 开启线程
  12. t1.start();
  13. t2.start();
  14. }
  15. }

00103_死锁、Lock接口、等待唤醒机制的更多相关文章

  1. java多线程(死锁,lock接口,等待唤醒机制)

    一.Lock接口 常用方法 Lock提供了一个更加面对对象的锁,在该锁中提供了更多的操作锁的功能. 使用Lock接口,以及其中的lock()方法和unlock()方法替代同步,对电影院卖票案例中Tic ...

  2. 死锁、Lock锁、等待唤醒机制、线程组、线程池、定时器、单例设计模式_DAY24

    1:线程(理解) (1)死锁 概念: 同步中,多个线程使用多把锁之间存在等待的现象. 原因分析: a.线程1将锁1锁住,线程2将锁2锁住,而线程1要继续执行锁2中的代码,线程2要继续执行锁1中的代码, ...

  3. java ->多线程_线程同步、死锁、等待唤醒机制

    线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. l  我们通过一个案例,演示线 ...

  4. 多线程之间的通信(等待唤醒机制、Lock 及其它线程的方法)

    一.多线程之间的通信. 就是多个线程在操作同一份数据, 但是操作的方法不同. 如: 对于同一个存储块,其中有两个存储位:name   sex, 现有两个线程,一个向其中存放数据,一个打印其中的数据. ...

  5. JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

    JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是clas ...

  6. “全栈2019”Java多线程第三十二章:显式锁Lock等待唤醒机制详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  7. Java多线程02(线程安全、线程同步、等待唤醒机制)

    Java多线程2(线程安全.线程同步.等待唤醒机制.单例设计模式) 1.线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量 ...

  8. java基础(27):线程安全、线程同步、等待唤醒机制

    1. 多线程 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. 我们通过一个案例,演示线程 ...

  9. java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)

     *java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时 ...

随机推荐

  1. hiho week 38 P1 : 二分·二分答案

    P1 : 二分·二分答案 Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB 描述 在上一回和上上回里我们知道Nettle在玩&l ...

  2. 使用UltraEdit配置多行注释和取消多行注释

    UltraEdit功能强大,使用方便,成为软件开发者必备的文档和代码编辑工具.有很多人也直接用它来写代码,如C/Java,脚本如:Perl/Tcl/JavaScript 等. 如果用来写代码,有一个不 ...

  3. Vijos——T1626 爱在心中

    https://vijos.org/p/1626 描述 “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our H ...

  4. 13.2 UPDATE

    13.2 UPDATE正在更新内容.请稍后

  5. Zabbix + Grafana

    Grafana 简介 Grafana自身并不存储数据,数据从其它地方获取.需要配置数据源 Grafana支持从Zabbix中获取数据 Grafana优化了图形的展现,可以用来做监控大屏 Grafana ...

  6. idea配置spark运行模式

    1. 配置运行参数: Menu -> Run -> Edit Configurations -> 选择 + -> Application   -Dspark.master=lo ...

  7. 源码安装 ipython

    https://blog.csdn.net/huobanjishijian/article/details/51470898

  8. 【Codeforces Round #428 (Div. 2) B】Game of the Rows

    [Link]:http://codeforces.com/contest/839/problem/B [Description] 给你n排的如题目所示的位置; 同一排中(1,2) 算相邻; (3,4) ...

  9. FZU 1962 新击鼓传花游戏

    新击鼓传花游戏 Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on FZU. Original ID: 19 ...

  10. js08--函数1

    函数当成类看当成匿名对象看,都是跟java吻合的,只有当成函数看(函数自己可以执行)跟java区别在这里. function fact(){} var F = fact ; 函数名是函数对象的地址,是 ...