两个线程 A 和 B
A做加法 B做减法
有时候正常无限计算下去
但有时 出现死锁
死锁输出如下:
增加后结果:1
增加后结果:2
增加后结果:3
增加后结果:4
增加后结果:5
add begin to wait
代码如下:我就不明白 为什么会死锁?public class AddReduceTestAgain {
/**
* @param args
*/
private int num = 0; private Add add = null; private Reduce reduce = null;
public static void main(String[] args) {
// TODO Auto-generated method stub
// Runnable r = new AddReduce();
AddReduceTestAgain ar = new AddReduceTestAgain(); Runnable r1 = ar.getAdd(ar); Runnable r2 = ar.getReduce(ar); Thread th1 = new Thread(r1, "th1");
Thread th2 = new Thread(r2, "th2"); th1.start();
th2.start(); } public Add getAdd(AddReduceTestAgain arTest) {
if (add == null) {
add = new Add(arTest);
}
return add;
} public Reduce getReduce(AddReduceTestAgain arTest) {
if (reduce == null) {
reduce = new Reduce(arTest);
}
return reduce;
} public void addMethord() {
while (num < 5) {
num += 1;
try {
Thread.currentThread().sleep(500);
} catch (Exception e) {
e.printStackTrace();
} synchronized (getAdd(AddReduceTestAgain.this)) {
System.out.println(" 增加后结果:" + num);
if (num >= 0)
getAdd(AddReduceTestAgain.this).notify();
} if (num >= 5) {
try {
synchronized (getReduce(AddReduceTestAgain.this)) {
System.out.println(" add begin to wait ");
getReduce(AddReduceTestAgain.this).wait();
}//这里执行完后已经 释放getReduce(AddReduceTestAgain.this)对象 } catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} public void reduceMethod() {
while (num > 0) {
num -= 1;
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
} synchronized (getReduce(AddReduceTestAgain.this)) { //为什么这里拿不到getReduce(AddReduceTestAgain.this)这个锁
System.out.println("减少后结果:" + num);
if (num < 5)
getReduce(AddReduceTestAgain.this).notify();
} if (num <= 0) {
try { synchronized (getAdd(AddReduceTestAgain.this)) { System.out.println(" reduce begin to wait ");
getAdd(AddReduceTestAgain.this).wait();
} } catch (InterruptedException e) {
e.printStackTrace();
}
} } } class Add implements Runnable {
AddReduceTestAgain arTest = null; public Add(AddReduceTestAgain art) {
arTest = art;
} public void run() {
arTest.addMethord();
} } class Reduce implements Runnable {
AddReduceTestAgain arTest = null; public Reduce(AddReduceTestAgain art) {
arTest = art;
} public void run() {
arTest.reduceMethod();
} }}
A做加法 B做减法
有时候正常无限计算下去
但有时 出现死锁
死锁输出如下:
增加后结果:1
增加后结果:2
增加后结果:3
增加后结果:4
增加后结果:5
add begin to wait
代码如下:我就不明白 为什么会死锁?public class AddReduceTestAgain {
/**
* @param args
*/
private int num = 0; private Add add = null; private Reduce reduce = null;
public static void main(String[] args) {
// TODO Auto-generated method stub
// Runnable r = new AddReduce();
AddReduceTestAgain ar = new AddReduceTestAgain(); Runnable r1 = ar.getAdd(ar); Runnable r2 = ar.getReduce(ar); Thread th1 = new Thread(r1, "th1");
Thread th2 = new Thread(r2, "th2"); th1.start();
th2.start(); } public Add getAdd(AddReduceTestAgain arTest) {
if (add == null) {
add = new Add(arTest);
}
return add;
} public Reduce getReduce(AddReduceTestAgain arTest) {
if (reduce == null) {
reduce = new Reduce(arTest);
}
return reduce;
} public void addMethord() {
while (num < 5) {
num += 1;
try {
Thread.currentThread().sleep(500);
} catch (Exception e) {
e.printStackTrace();
} synchronized (getAdd(AddReduceTestAgain.this)) {
System.out.println(" 增加后结果:" + num);
if (num >= 0)
getAdd(AddReduceTestAgain.this).notify();
} if (num >= 5) {
try {
synchronized (getReduce(AddReduceTestAgain.this)) {
System.out.println(" add begin to wait ");
getReduce(AddReduceTestAgain.this).wait();
}//这里执行完后已经 释放getReduce(AddReduceTestAgain.this)对象 } catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} public void reduceMethod() {
while (num > 0) {
num -= 1;
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
} synchronized (getReduce(AddReduceTestAgain.this)) { //为什么这里拿不到getReduce(AddReduceTestAgain.this)这个锁
System.out.println("减少后结果:" + num);
if (num < 5)
getReduce(AddReduceTestAgain.this).notify();
} if (num <= 0) {
try { synchronized (getAdd(AddReduceTestAgain.this)) { System.out.println(" reduce begin to wait ");
getAdd(AddReduceTestAgain.this).wait();
} } catch (InterruptedException e) {
e.printStackTrace();
}
} } } class Add implements Runnable {
AddReduceTestAgain arTest = null; public Add(AddReduceTestAgain art) {
arTest = art;
} public void run() {
arTest.addMethord();
} } class Reduce implements Runnable {
AddReduceTestAgain arTest = null; public Reduce(AddReduceTestAgain art) {
arTest = art;
} public void run() {
arTest.reduceMethod();
} }}
本人认为在这段代码中没有必要为getAdd()和getReduce,也就是add和reduce成员引用进行同步。因为这两个变量,两个线程分别指向它们其中之一。
以下是我的代码: public void addMethord() {
int tempNum;
while (true) {
synchronized(num) {
if(num < 5)
num++;
tempNum = num;
}
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(" 增加后结果:" + tempNum);
try {
if(num >= 5) {
getReduce(this).notify();
getAdd(this).wait();
}
}
catch(InterruptedException e) {
}
catch(IllegalMonitorStateException e) {
System.out.println("Thread add notifies Thread reduce!");
}
}
} public void reduceMethod() {
int tempNum;
while (true) {
synchronized(num) {
if(num > 0)
num--;
tempNum = num;
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" 减少后结果:" + tempNum);
try {
if (num <= 0) {
getAdd(this).notify();
getReduce(this).wait();
}
}
catch(InterruptedException e) {
}
catch(IllegalMonitorStateException e) {
System.out.println("Thread reduce notifies Thread add!");
}
}
}
另外,我对num用volatile进行了修饰。
经过5次测试,没有发生死锁。
以下输出结果是分别对getReduce(this).notify();和getAdd(this).notify();这两句加上断点后,在调试模式下测试的。也没有问题。 增加后结果:1
减少后结果:0
增加后结果:1
减少后结果:0
增加后结果:1
减少后结果:0
增加后结果:1
减少后结果:0
增加后结果:1
减少后结果:0
增加后结果:1
减少后结果:0
增加后结果:1
减少后结果:0
增加后结果:1
减少后结果:0
增加后结果:1
减少后结果:0
增加后结果:1
减少后结果:0
增加后结果:1
减少后结果:0
减少后结果:0
增加后结果:1
增加后结果:1
增加后结果:2
增加后结果:3
增加后结果:4
增加后结果:5
Thread reduce notifies Thread add!
减少后结果:4
减少后结果:3
减少后结果:2
减少后结果:1
减少后结果:0
Thread add notifies Thread reduce!
增加后结果:1
增加后结果:2
增加后结果:3
增加后结果:4
增加后结果:5
Thread reduce notifies Thread add!
减少后结果:4
减少后结果:3
减少后结果:2
减少后结果:1
减少后结果:0
我是这么理解的num -= 1;后被另一个线程抢占,执行num += 1;
然后
if (num > = 5) {
try {
synchronized (getReduce(AddReduceTestAgain.this)) {
System.out.println(" add begin to wait ");
getReduce(AddReduceTestAgain.this).wait();
}//这里执行完后已经 释放getReduce(AddReduceTestAgain.this)对象} catch (InterruptedException e) {
e.printStackTrace();
} 不知道这样能不能得到锁!!!
我知道 我的问题出在哪了 基于你的code 我发现我遇到的不是死锁 而是在addMethord中 我的while执行结束了 也就是此时add线程已经执行完了 这个时候在reduceMethord调用add.notify也是没有用的 呵呵 你说的对 我的addMethord和reduceMethord别扭就别扭在while上
对于这段code wait和notify确实不用加同步块 因为add对象和reduce对象各只有一个线程再跑 而且我个人认为如果只有一个add对象的n个线程在跑和有只有一个reduce对象的n个线程在跑的话 都不用外wait和notify上加同步块 当多个add对象多个reduce对象及他们对应的线程时 此时wait和notify同步块必须加 不知道这句话对不对 不过我还是喜欢在wait()和notify上加同步块 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% badonly Thread.currentThread().sleep(500); 因为控制台显示结果太快了 让它慢点 让线程睡一会再打
还有个问题 这是我第一次发帖 怎么给别人加分 -_-!