public class printDemo04 {
public static void main(String[] args) {
Resource01 resource01 = new Resource01();
Producer producer = new Producer(resource01);
Producers producers = new Producers(resource01);
Thread thread0 = new Thread(producer);
Thread thread1 = new Thread(producer);
Thread thread2 = new Thread(producers);
Thread thread3 = new Thread(producers);
thread0.start();
thread1.start();
thread2.start();
thread3.start();
}
}
class Resource01{
private String name;
private int sex = 1;
private boolean flag = false;
public synchronized void setSth(String name){
while(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name+sex;
sex++;
System.out.println(Thread.currentThread().getName()+"----"+"生产者..."+this.name);
flag = true;
this.notifyAll();
} public synchronized void getSth(){
while(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"--"+"消费者..."+name);
flag = false;
this.notifyAll();
}
}
class Producer implements Runnable{
Resource01 resource01;
public Producer(Resource01 resource01) {
this.resource01 = resource01;
}
int i = 1;
@Override
public void run() {
while(true){
if(i==1){
resource01.setSth("烤鸭");
}
i = (i+1)%2;
}
}
}
class Producers implements Runnable{
Resource01 resource01;
public Producers(Resource01 resource01) {
this.resource01 = resource01;
} @Override
public void run() {
while(true){
resource01.getSth();
}
}
}

  死锁发生的情况:上述代码中,把标色的this.notifyAll();改为this.notify();就会发生线程的死锁,为什么呢?应为代码中总共有4个线程,生产者1和生产者2,消费者1和消费者2。理想状态是生产者1和生产者2执行生产操作,消费者1和消费者2执行消费操作,生产一个,消费一个。现在线程进入首先执行生产操作,打个比方生产1生产了烤鸭1,然后flag等于true,如果接下来执行的生产操作的话,这个生产线程就会被等待,这时候执行的生产者2,就会被等待,接下来执行消费者2线程消费者2线程执行完以后flag为false,这时候有要选择一个线程执行,因为生产者2在线程池中被等待,所以现在只能执行生产者1、消费者1和消费者2,假设这时候执行生产者1又生产了烤鸭2,然后又在前面三个线程中选择了生产者1,这时候flag为true,生产者1又进入了线程池进行了等待。然后线程只有2个可以执行消费者1和消费者2,这时候消费完以后,flag为false,接下来只能执行消费线程,但是没法生产flag就只能为false,所以这时候消费者1和消费者2就都会被等待,到此为止,4个线程都被等待,于是就发生了死锁。使用notifyAll()就不会发生死锁了。

  while在这的作用是判断当前执行的线程是否应该被执行,就像代码中所表示的执行完生产只能消费。

线程死锁情况和while在线程的作用的更多相关文章

  1. .NET Core中遇到奇怪的线程死锁问题:内存与线程数不停地增长

    一个 asp.net core 站点,之前运行在Linux 服务器上,运行一段时间后有时站点会挂掉,在日志中记录很多“EMFILE too many open files”的错误: Microsoft ...

  2. 并发编程-线程-死锁现象-GIL全局锁-线程池

    一堆锁 死锁现象 (重点) 死锁指的是某个资源被占用后,一直得不到释放,导致其他需要这个资源的线程进入阻塞状态. 产生死锁的情况 对同一把互斥锁加了多次 一个共享资源,要访问必须同时具备多把锁,但是这 ...

  3. 尝试解决在构造函数中同步调用Dns.GetHostAddressesAsync()引起的线程死锁

    (最终采用的是方法4) 问题详情见:.NET Core中遇到奇怪的线程死锁问题:内存与线程数不停地增长 看看在 Linux 与 Windows 上发生线程死锁的后果. Linux: Microsoft ...

  4. .net学习之多线程、线程死锁、线程通信 生产者消费者模式、委托的简单使用、GDI(图形设计接口)常用的方法

    1.多线程简单使用(1)进程是不执行代码的,执行代码的是线程,一个进程默认有一个线程(2)线程默认情况下都是前台线程,要所有的前台线程退出以后程序才会退出,进程里默认的线程我们叫做主线程或者叫做UI线 ...

  5. 55行代码实现Java线程死锁

    死锁是Java多线程的重要概念之一,也经常出现在各大公司的笔试面试之中.那么如何创造出一个简单的死锁情况?请看代码: class Test implements Runnable { boolean ...

  6. 对象及变量的并发访问(同步方法、同步代码块、对class进行加锁、线程死锁)&内部类的基本用法

    主要学习多线程的并发访问,也就是使得线程安全. 同步的单词为synchronized,异步的单词为asynchronized 同步主要就是通过锁的方式实现,一种就是隐式锁,另一种是显示锁Lock,本节 ...

  7. java命令分析线程死锁以及内存泄漏

    一.介绍 jstack是java虚拟机自带的一种堆栈跟踪工具.jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项&qu ...

  8. Python并发编程-进程 线程 同步锁 线程死锁和递归锁

    进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ...

  9. Atitit.线程 死锁 跑飞 的检测与自动解除 与手动解除死锁 java c# .net php javascript.

    Atitit.线程 死锁 跑飞 的检测与自动解除 与手动解除死锁 java c# .net php javascript. 1. 现象::主程序卡住无反应,多行任务不往下执行 1 2. 原因::使用j ...

随机推荐

  1. PHP面向对象(分页)

    <?php   class page   {      var $table;      var $pagesize;      var $totalsize;      var $totalp ...

  2. [USACO08DEC] Trick or Treat on the Farm

    题目描述 每年万圣节,威斯康星的奶牛们都要打扮一番,出门在农场的N个牛棚里转 悠,来采集糖果.她们每走到一个未曾经过的牛棚,就会采集这个棚里的1颗糖果. 农场不大,所以约翰要想尽法子让奶牛们得到快乐. ...

  3. java之main

    Java中用户向系统传递参数的三种基本方式 main方法 在Java中,main()方法是Java应用程序的入口方法,也就是说,程序在运行的时候,第一个执行的方法就是main()方法,这个方法和其他的 ...

  4. Sqlserver推荐参数配置及日志收缩问题

    最近不定期有项目反馈周期性的系统整体性能下降情况,经分析存在因数据库环境.参数配置不佳造成的.比如,sqlserver日志文件缺省按百分比增长,当日志文件已经比较大时,每次扩展时耗时较长,系统整体卡顿 ...

  5. HackerRank "Kitty and Katty"

    It's more of a brain-teaser than a Game Theory problem.. #!/bin/python3 T = int(input().strip()) for ...

  6. python---sys

    简介 sys模块用于提供对python解释器的相关操作 sys.argv 命令行参数List,第一个元素是程序本身路径 sys.modules 返回系统导入的模块字段,key是模块名,value是模块 ...

  7. ThinkPHP 3.2.3心得

    个人还是蛮喜欢tp的比其他的php框架轻(只接触过drupal.tp),而且上手容易(struts这种action的方式,对于java程序员来说).目录结构也比较简单易懂,提供的一些函数也比较实用.对 ...

  8. 60. Insert Interval && Merge Intervals

    Insert Interval Given a set of non-overlapping intervals, insert a new interval into the intervals ( ...

  9. Hardmard 变换

    阿达马(Hadamard)矩阵是由+1和-1元素构成的正交方阵.阿达马变换多被用来计算SATD(一种视频残差信号大小的衡量). 这里介绍三个内容,1. SATD 2. H264中阿达马的应用 3. 阿 ...

  10. Linux字符界面下用户账户的设置

    在Linux系统字符界面下创建.修改以及删除用户账户主要使用useradd,usermod和userdel这3个命令. 一.创建用户账户 创建用户账户就是在系统中创建一个新账户,然后为新账户分配用户U ...