0 in 3 in 2 in 1 in 2 out(sleep) 3 out(decrease) 0 out(increase) 1 out(increase) 2 in main exit 3 exit 1 exit 0 exit 2 out(decrease) 2 exit 这是一个测试的例子 大家可以看到 2 in 之后程序就死锁了 直到 main exit 才有 2 out
0 in 3 in 2 in 2 out(sleep) 1 in 1 out(increase) 1 in 1 out(decrease) 3 out(decrease) 3 in 3 out(sleep) 0 out(increase) 0 in 0 out(increase) 0 in 1 in 0 out(decrease) 1 out(sleep) 2 in 2 out(increase) 2 in 2 out(decrease) 0 in 0 out(sleep) 3 in 3 out(increase) 3 in 2 in 2 out(sleep) 3 out(decrease) 1 in 1 out(increase) 1 in 3 in 3 out(decrease) 1 out(sleep) 0 in 0 out(increase) 0 in 0 out(decrease) 3 in 3 out(sleep) 2 in 2 out(increase) 2 in 0 in 0 out(sleep) 2 out(decrease) 1 in 1 out(increase) 1 in 1 out(decrease) 2 in 2 out(sleep) 3 in 3 out(increase) 3 in 1 in 3 out(decrease) 1 out(sleep) 0 in 0 out(increase) 0 in 0 out(decrease) 3 in 3 out(sleep) 2 in 2 out(increase) 2 in 0 in 2 out(decrease) 0 out(sleep) 1 in 1 out(increase) 1 in 2 in 2 out(sleep) 1 out(decrease) 3 in 3 out(increase) 3 in 1 in 1 out(decrease) 3 out(sleep) 0 in 0 out(increase) 0 in 0 out(decrease) 1 in 1 out(sleep) 2 in 2 out(increase) 2 in 0 in 0 out(sleep) 2 out(decrease) 3 in 3 out(increase) 3 in 3 out(decrease) 2 in 2 out(sleep) 1 in 1 out(increase) 1 in 3 in 3 out(sleep) 1 out(decrease) 0 in 0 out(increase) 0 in 0 out(decrease) 0 in 0 out(sleep) 3 in 3 out(increase) 3 in 3 out(decrease) 1 in 2 in 2 out(sleep) 1 out(increase) 3 in 3 out(decrease) 1 in 1 out(sleep) 0 in 0 out(increase) 0 in 0 out(decrease) 3 in 3 out(sleep) 2 in 2 out(increase) 2 in 0 in 0 out(sleep) 2 out(decrease) 1 in 1 out(increase) 1 in 1 out(decrease) 2 in 2 out(sleep) 3 in 3 out(increase) 3 in 1 in 1 out(decrease) 3 out(sleep) 0 in 0 out(increase) 0 in 0 out(decrease) 1 in 1 out(sleep) 2 in 2 out(increase) 2 in 0 in 0 out(sleep) 2 out(decrease) 3 in 3 out(increase) 3 in 3 out(decrease) 2 in 2 out(sleep) 1 in 1 out(increase) 1 in 3 in 1 out(decrease) 3 out(sleep) 0 in 0 out(increase) 0 in 1 in 0 out(decrease) 1 out(sleep) 2 in 2 out(increase) 2 in 0 in 0 out(decrease) 2 out(sleep) 3 in 3 out(increase) 3 in 3 out(decrease) 0 in 0 out(sleep) 1 in 1 out(increase) 1 in 1 out(decrease) 3 in 3 out(sleep) .......ConcurrentLinkedQueue本来就是线程安全的 把add和poll的synchronized去掉后 输出如上,可见已经正常运行了 可是为什么死锁还是没有头绪 ,大家有什么看法?
我上面的说法有些错误,我重发一下代码 import java.util.concurrent.ConcurrentLinkedQueue;public class Routine { public static final void main(String[] args) { ThreadMain m = new ThreadMain(); try { Thread.sleep(20000); } catch (InterruptedException e) { } m.getData().setRun(false); System.out.print("main exit\n"); } }class ThreadData { private boolean mRun; private ConcurrentLinkedQueue<Integer> mWait; private int mValue; public ThreadData() { mRun = true; mWait = new ConcurrentLinkedQueue<Integer>(); mValue = 0; } public void add(Integer i) { mWait.add(i); } public Integer poll() { return mWait.poll(); } public void increase(Integer i) { mValue += i.intValue(); } public synchronized void decrease(Integer i) { while (mRun && mValue < i.intValue()) ; if (mRun) { mValue -= i.intValue(); } } public boolean getRun() { return mRun; } public void setRun(boolean r) { mRun = r; } }class ThreadMain implements Runnable { private ThreadData mData; private Thread[] mRuns; public ThreadMain() { mData = new ThreadData(); for (int i = 0; i < 100; i++) mData.add(Integer.valueOf((int) (Math.random() * 200))); mRuns = new Thread[4]; for (int i = 0; i < mRuns.length; i++) { mRuns[i] = new Thread(this); mRuns[i].start(); } } @Override public void run() { String[] names = { "increase", "decrease", "sleep" }; int mId ; for (mId = 0 ; mId < mRuns.length && Thread.currentThread() != mRuns[mId] ; mId++) ;
while (mData.getRun()) { Integer i; System.out.printf("%d in\n", mId); do { i = mData.poll(); } while (mData.getRun() && i == null); if (mData.getRun() == false) break; System.out.printf("%d out(%s)\n", mId, names[i.intValue() % 3]); switch (i.intValue() % 3) { case 0: mData.increase(i); break; case 1: mData.decrease(i); break; case 2: try { Thread.sleep(1000); } catch (InterruptedException e) { } break; } } System.out.printf("%d exit\n", mId); } public ThreadData getData() { return mData; } } 正确的 ,测试输出 1 in 3 in 2 in 0 in 2 out(increase) 3 out(decrease) 1 out(decrease) 3 in 3 out(sleep) 2 in 2 out(sleep) 0 out(increase) 0 in 0 out(increase) 1 in 0 in 1 out(decrease) 0 out(sleep) 1 in 1 out(increase) 1 in 1 out(sleep) 3 in 0 in 0 out(decrease) 2 in 2 out(decrease) 2 in 2 out(decrease) 2 in 2 out(decrease) 0 in 0 out(increase) 0 in 0 out(decrease) 1 in 1 out(sleep) 3 out(sleep) 1 in 1 out(decrease) 3 in 3 out(decrease) main exit 0 exit 2 exit 1 exit 3 exit 我发现问题还出在increase的synchronized 上 下面是increase加了synchronized的 死锁的 ,测试输出 0 in 3 in 1 in 2 in 1 out(increase) 3 out(decrease) 0 out(decrease) 1 in 1 out(decrease) 2 out(increase) main exit 0 exit 1 exit 2 exit 3 exit
3 in
2 in
1 in
2 out(sleep)
3 out(decrease)
0 out(increase)
1 out(increase)
2 in
main exit
3 exit
1 exit
0 exit
2 out(decrease)
2 exit
这是一个测试的例子
大家可以看到
2 in
之后程序就死锁了
直到
main exit
才有
2 out
但是为甚0 1 2线程,都停止了呢?
大家看ThreadMain构造 ,是有100组Integer的
不可能是因为队列空而,等待
0和1甚至根本没输出in
说明0 1死锁在increase中
2死锁在poll中
是因为3一直在synchronized decrease中吗?
synchronized不是只限制同函数不被同时执行吗
为什么3 decrease
导致
0 1 2 调用的函数均失败了?
3 in
2 in
2 out(sleep)
1 in
1 out(increase)
1 in
1 out(decrease)
3 out(decrease)
3 in
3 out(sleep)
0 out(increase)
0 in
0 out(increase)
0 in
1 in
0 out(decrease)
1 out(sleep)
2 in
2 out(increase)
2 in
2 out(decrease)
0 in
0 out(sleep)
3 in
3 out(increase)
3 in
2 in
2 out(sleep)
3 out(decrease)
1 in
1 out(increase)
1 in
3 in
3 out(decrease)
1 out(sleep)
0 in
0 out(increase)
0 in
0 out(decrease)
3 in
3 out(sleep)
2 in
2 out(increase)
2 in
0 in
0 out(sleep)
2 out(decrease)
1 in
1 out(increase)
1 in
1 out(decrease)
2 in
2 out(sleep)
3 in
3 out(increase)
3 in
1 in
3 out(decrease)
1 out(sleep)
0 in
0 out(increase)
0 in
0 out(decrease)
3 in
3 out(sleep)
2 in
2 out(increase)
2 in
0 in
2 out(decrease)
0 out(sleep)
1 in
1 out(increase)
1 in
2 in
2 out(sleep)
1 out(decrease)
3 in
3 out(increase)
3 in
1 in
1 out(decrease)
3 out(sleep)
0 in
0 out(increase)
0 in
0 out(decrease)
1 in
1 out(sleep)
2 in
2 out(increase)
2 in
0 in
0 out(sleep)
2 out(decrease)
3 in
3 out(increase)
3 in
3 out(decrease)
2 in
2 out(sleep)
1 in
1 out(increase)
1 in
3 in
3 out(sleep)
1 out(decrease)
0 in
0 out(increase)
0 in
0 out(decrease)
0 in
0 out(sleep)
3 in
3 out(increase)
3 in
3 out(decrease)
1 in
2 in
2 out(sleep)
1 out(increase)
3 in
3 out(decrease)
1 in
1 out(sleep)
0 in
0 out(increase)
0 in
0 out(decrease)
3 in
3 out(sleep)
2 in
2 out(increase)
2 in
0 in
0 out(sleep)
2 out(decrease)
1 in
1 out(increase)
1 in
1 out(decrease)
2 in
2 out(sleep)
3 in
3 out(increase)
3 in
1 in
1 out(decrease)
3 out(sleep)
0 in
0 out(increase)
0 in
0 out(decrease)
1 in
1 out(sleep)
2 in
2 out(increase)
2 in
0 in
0 out(sleep)
2 out(decrease)
3 in
3 out(increase)
3 in
3 out(decrease)
2 in
2 out(sleep)
1 in
1 out(increase)
1 in
3 in
1 out(decrease)
3 out(sleep)
0 in
0 out(increase)
0 in
1 in
0 out(decrease)
1 out(sleep)
2 in
2 out(increase)
2 in
0 in
0 out(decrease)
2 out(sleep)
3 in
3 out(increase)
3 in
3 out(decrease)
0 in
0 out(sleep)
1 in
1 out(increase)
1 in
1 out(decrease)
3 in
3 out(sleep)
.......ConcurrentLinkedQueue本来就是线程安全的
把add和poll的synchronized去掉后
输出如上,可见已经正常运行了
可是为什么死锁还是没有头绪 ,大家有什么看法?
import java.util.concurrent.ConcurrentLinkedQueue;public class Routine {
public static final void main(String[] args) {
ThreadMain m = new ThreadMain();
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
}
m.getData().setRun(false);
System.out.print("main exit\n");
}
}class ThreadData {
private boolean mRun;
private ConcurrentLinkedQueue<Integer> mWait;
private int mValue; public ThreadData() {
mRun = true;
mWait = new ConcurrentLinkedQueue<Integer>();
mValue = 0;
} public void add(Integer i) {
mWait.add(i);
} public Integer poll() {
return mWait.poll();
} public void increase(Integer i) {
mValue += i.intValue();
} public synchronized void decrease(Integer i) {
while (mRun && mValue < i.intValue())
;
if (mRun) {
mValue -= i.intValue();
}
} public boolean getRun() {
return mRun;
} public void setRun(boolean r) {
mRun = r;
}
}class ThreadMain implements Runnable {
private ThreadData mData;
private Thread[] mRuns; public ThreadMain() {
mData = new ThreadData();
for (int i = 0; i < 100; i++)
mData.add(Integer.valueOf((int) (Math.random() * 200)));
mRuns = new Thread[4];
for (int i = 0; i < mRuns.length; i++) {
mRuns[i] = new Thread(this);
mRuns[i].start();
}
} @Override
public void run() {
String[] names = { "increase", "decrease", "sleep" };
int mId ;
for (mId = 0 ; mId < mRuns.length && Thread.currentThread() != mRuns[mId] ; mId++) ;
while (mData.getRun()) {
Integer i;
System.out.printf("%d in\n", mId);
do {
i = mData.poll();
} while (mData.getRun() && i == null);
if (mData.getRun() == false)
break;
System.out.printf("%d out(%s)\n", mId, names[i.intValue() % 3]); switch (i.intValue() % 3) {
case 0:
mData.increase(i);
break;
case 1:
mData.decrease(i);
break;
case 2:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
break;
}
} System.out.printf("%d exit\n", mId);
} public ThreadData getData() {
return mData;
}
}
正确的 ,测试输出
1 in
3 in
2 in
0 in
2 out(increase)
3 out(decrease)
1 out(decrease)
3 in
3 out(sleep)
2 in
2 out(sleep)
0 out(increase)
0 in
0 out(increase)
1 in
0 in
1 out(decrease)
0 out(sleep)
1 in
1 out(increase)
1 in
1 out(sleep)
3 in
0 in
0 out(decrease)
2 in
2 out(decrease)
2 in
2 out(decrease)
2 in
2 out(decrease)
0 in
0 out(increase)
0 in
0 out(decrease)
1 in
1 out(sleep)
3 out(sleep)
1 in
1 out(decrease)
3 in
3 out(decrease)
main exit
0 exit
2 exit
1 exit
3 exit
我发现问题还出在increase的synchronized
上
下面是increase加了synchronized的
死锁的 ,测试输出
0 in
3 in
1 in
2 in
1 out(increase)
3 out(decrease)
0 out(decrease)
1 in
1 out(decrease)
2 out(increase)
main exit
0 exit
1 exit
2 exit
3 exit
错误输出
2 out
之后,程序就没反应了
直到
main exit
各个线程才退出
2 out(increase)
指的是2线程成功从队列中获取数据,接下来执行increase操作
你再看看increase函数
这个函数可能会让线程2执行那么久吗
只有一个可能2被挂起了
但是这个函数会引起线程拥挤吗
显然不会!!!
但是线程2还是被挂起了
这不是死锁是什么还有我原本是学c的
我按照这段代码 ,用c++和临界区写了个同样思路的代码
结果完全正常 ,不管我在哪个函数加临界区
程序都正常执行
但换到java就这样
是java执行太慢吗?
是我没理解synchronized吗?
我怎么想都不合理最后只得出一个结论
java就是这样罢了
最后我发的代码是没问题的
有问题的代码是这段代码的increase函数
加上了synchronized
才会引起问题哎,算了,我结贴了
如果有人明白了请@我,求教
如果不知道发生了什么问题
或者没时间去研究,那就ctrl+w吧