为什么把IF放到synchronized里面没事,但是放到线程外面就会发现有卡死(死锁)现象,逻辑上是不是出现问题,希望个位指点一下。。
class Bread
{
String name = "起司";
int count=0;
boolean flag = false;
}class Maker implements Runnable
{
Bread s ;
Maker(Bread s)
{
this.s = s;
}
public void run()
{
while(true)
{
synchronized(s)
{
if(!s.flag)
{
s.count++;
System.out.println("面包师傅生产了"+s.name+"........"+s.count);
s.flag = true;
}
}
}
}
}class Consumer implements Runnable
{
Bread s ;
Consumer(Bread s)
{
this.s = s;
}
public void run()
{
while(true)
{
synchronized(s)
{
if(s.flag)
{
class Bread
{
String name = "起司";
int count=0;
boolean flag = false;
}class Maker implements Runnable
{
Bread s ;
Maker(Bread s)
{
this.s = s;
}
public void run()
{
while(true)
{
synchronized(s)
{
if(!s.flag)
{
s.count++;
System.out.println("面包师傅生产了"+s.name+"........"+s.count);
s.flag = true;
}
}
}
}
}class Consumer implements Runnable
{
Bread s ;
Consumer(Bread s)
{
this.s = s;
}
public void run()
{
while(true)
{
synchronized(s)
{
if(s.flag)
{
解决方案 »
- 一道简单的Java题
- DB2 JDBC failed on sum a DOUBLE TYPE 202601.84 + 249494.82=452096.660000003
- jaxb将java对象映射成xml
- 自己写一个加减乘除程序,并采用junit对其进行测试
- 我是初学者 请问getInstance在抽象类中是咋用的?
- 跪求《Java实用编程100例》的源代码
- 如何改变java application 的风格
- 关于初始化的一个问题!!
- 求一个JTree的简单例子
- 推荐几本JAVA和OOP思想的好书
- 请高人解释下这段递归代码!
- DatagramSocket.receive无限阻塞,占用线程,导致一段时间过后线程全部被占用
class Bread
{
String name = "起司";
int count=0;
boolean flag = false;
}class Maker implements Runnable
{
Bread s ;
Maker(Bread s)
{
this.s = s;
}
public void run()
{
while(true)
{
if(!s.flag)
{
synchronized(s)
{
s.count++;
System.out.println("面包师傅生产了"+s.name+"........"+s.count);
s.flag = true;
}
}
}
}
}class Consumer implements Runnable
{
Bread s ;
Consumer(Bread s)
{
this.s = s;
}
public void run()
{
while(true)
{
if(s.flag)
{
synchronized(s)
{
System.out.println("胖子消费了"+s.name+"........"+s.count);
s.count--;
s.flag = false;
}
} }
}
}class Test
{
public static void main(String[] args)
{
Bread s = new Bread();
Maker a = new Maker(s);
Consumer b = new Consumer(s);
Thread t = new Thread(a);
Thread t2 = new Thread(b);
t.start();
t2.start();
}
}
package a;class Bread {
String name = "起司";
int count=0;
boolean flag = false;
}
class Maker implements Runnable {
Bread s ;
Maker(Bread s) {
this.s = s;
}
public void run() {
while(true) {
try{
Thread.sleep(10);
}catch(Exception ex){}
if(!s.flag) {
synchronized(s) {
s.count++;
System.out.println("面包师傅生产了"+s.name+"........"+s.count);
s.flag = true;
}
}
}
}
}class Consumer implements Runnable {
Bread s ;
Consumer(Bread s) {
this.s = s;
}
public void run() {
while(true) {
try{
Thread.sleep(10);
}catch(Exception ex){}
if(s.flag) {
synchronized(s) {
System.out.println("胖子消费了"+s.name+"........"+s.count);
s.count--;
s.flag = false;
}
}
}
}
}class Test {
public static void main(String[] args) {
Bread s = new Bread();
Maker a = new Maker(s);
Consumer b = new Consumer(s);
Thread t = new Thread(a);
Thread t2 = new Thread(b);
t.start();
t2.start();
}
}
楼主的程序应该不是死锁了,而是其中一个线程进入了死循环,并且没有被打断,导致另一个线程没有执行的机会,可能的情况是:初始时 s.flag = false
生产者执行 :
判断 !s.flag = true
锁 s
s.count++
打印
s.flag = true
释放锁
消费者:
s.flag = true
锁 s
打印
s.count--
s.flag = false
程序被打断 // 此时还没有释放锁
生产者:
!s.flag = true, 进入if语句块
尝试取得锁失败,等待消费者
释放锁
while 死循环
进入 if(s.flag) 语句,为 false, 继续 while(true) 语句,进入 if(s.flag) 判断为 false,继续 while(true) ……由于 while 语句没有被打断,导致生产者线程没有机会被执行,因此看起来象是死锁了如果在生产者和消费者的程序中者程序中加上休眠语句,让另外一个线程有机会执行,则不会“死锁”
+2 -1
使用 wait/notify 的模式控制线程共享资源是最好的办法
但是,楼主的线程不是被卡住了,而是一个线程进入死循环并且没有被打断,导致另一个线程没有机会执行。我按楼主的意思改了程序,发现“死锁”时,CPU利用率比较高,如果是十年前的单核CPU,估计会达到100%。
+1package a;import java.util.*;class Bread {
boolean stopFlag = false;
String name = "起司";
int count = 0;
public void make(){
synchronized(this){
// 库存超过10,则不再生产,等待消费者消耗库存
while(count >= 10){
try{
this.wait();
}catch(InterruptedException ex){
}
}
count++;
System.out.println("生产面包,当前库存:" + count);
this.notifyAll();
}
}
public void consume(){
synchronized(this){
// 如果库存为0,则等待生产者生产
while(count <= 0){
try{
this.wait();
}catch(InterruptedException ex){
}
}
count--;
System.out.println("消费者消费面包,当前库存:" + count);
this.notifyAll();
}
}
}class Maker implements Runnable {
Random rdm = new Random();
Bread s ;
Maker(Bread s) {
this.s = s;
}
public void run() {
while(true) {
try{
Thread.sleep(rdm.nextInt(100));
}catch(Exception ex){
}
s.make();
}
}
}class Consumer implements Runnable {
Random rdm = new Random();
Bread s ;
Consumer(Bread s) {
this.s = s;
}
public void run() {
while(true) {
try{
Thread.sleep(rdm.nextInt(100));
}catch(Exception ex){
}
s.consume();
}
}
}class Test {
public static void main(String[] args) {
Bread s = new Bread();
Maker a = new Maker(s);
Consumer b = new Consumer(s);
Thread t = new Thread(a);
Thread t2 = new Thread(b);
t.start();
t2.start();
}
}
+2 -1
使用 wait/notify 的模式控制线程共享资源是最好的办法
但是,楼主的线程不是被卡住了,而是一个线程进入死循环并且没有被打断,导致另一个线程没有机会执行。我按楼主的意思改了程序,发现“死锁”时,CPU利用率比较高,如果是十年前的单核CPU,估计会达到100%。正是因为flag不能被线程正确的赋值,所以才需要用wai() 和nofityall()控制,而且楼主的程序还需要检查count 是否大于0。 wait()和notifyall()跟死锁没关系,而是要控制线程之间的互动。
wait/notify 模式与楼主的思路最大的区别在于,wait/notify 是主动放弃线程的执行,等待其它线程唤醒;而楼主的思路是时刻进行询问。
这就象是
用楼主的办法:面包店的面包卖完了,胖子不停地问老板,面包做好了没,面包做好了没,面包做好了没……
而wait/notify 的办法是:面包店的面包卖完了,胖子坐在一边等,当老板的面包做好了,吆喝一声,面包出炉了,大家来买呀
class Bread
{
String name = "起司";
int count=0;
boolean flag = false;
}修改成
class Bread
{
String name = "起司";
int count=0;
volatile boolean flag = false;
}就不会卡死了, 具体原因说来话太长, 就不说了