楼主,你把那两行锁注释掉就没有这个问题了 解释: 以下这段代码不是线程安全的 Integer i = 0; synchronized(i) { i++; } ...... 原因是Java的自动封箱和解箱操作在作怪。 这里的i++实际上是i = new Integer(i+1),所以执行完i++后,i已经不是原来的对象了,同步块自然就无效了。其它基本类型的封装类,如Short、Long等等也不能作为同步对象。 so. 最好用专门的锁服务来完成互斥操作
这个肯定有可能出现死循环,之所在大家都没有出现死循环,是因为当好时间片段切换到了合适的线程,得以让线程继续下去.上述程序不出现死循环的结果肯定是"a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c ".这个程序,只要减少或者增加一个线程,就会马上出现死循环,楼主只用一个线程DEBUG一下马上就明白.上面之所以不出现死循环,是因为时间片切得刚刚好,第一个线程走完flag=1了,马上切到第二个线程,第二个线程走完flag=2又切到第三个线程,第三个走完flag=0又回到第一个线程.如此类推,每次flag的值刚好是线程输入的值,所以不出现死循环.但执行结果是一样的.倘若线程切得不准,立马就死循环了.
当时sflag+1==4;其他两个线程正好flag!=sflag,三个线程均死循环
解释:
以下这段代码不是线程安全的
Integer i = 0;
synchronized(i) {
i++;
}
......
原因是Java的自动封箱和解箱操作在作怪。
这里的i++实际上是i = new Integer(i+1),所以执行完i++后,i已经不是原来的对象了,同步块自然就无效了。其它基本类型的封装类,如Short、Long等等也不能作为同步对象。
so. 最好用专门的锁服务来完成互斥操作
10楼说的,“上面之所以不出现死循环,是因为时间片切得刚刚好,第一个线程走完flag=1了,马上切到第二个线程,第二个线程走完flag=2又切到第三个线程,第三个走完flag=0又回到第一个线程”,我觉得不太可能是这样。可以在run()方法里加一句输出:
System.out.println("current thtread is" + Thread.currentThread().getName());
就能看出来。
我执行了一下代码,没有碰到死循环的情况啊
现在倒推一下,出现死循环,就是count 始终大于0,count--无法执行,flag == sflag 一直不成立
三个线程的 flag 分别为 0、1、2 ,(正常情况下 sflag 的初始值为 0,值集合为{0,1,2}),但是 flag == sflag 一直不成立
所以 sflag 的值已经不再是{0,1,2},这种情况 怎么才会出现
private final int flag;
private static Integer sflag = 0;
private static Object lock = new Object(); public PrintThread(int flag) {
this.flag = flag;
} public void run() {
int count = 10;
while (count > 0) {
synchronized (lock) {
if (flag == sflag) {
System.out.print((char) ('a' + flag) + " ");
count--;
sflag = (sflag + 1) % 3;
lock.notifyAll();// 唤醒所有
} else {
try {
lock.wait();// 等待被唤醒,释放lock,唤醒时重新获取lock
} catch (InterruptedException ignore) {
}
}
}
}
}
}public class Wait { public static void main(String[] args) {
PrintThread pt0 = new PrintThread(0);
PrintThread pt1 = new PrintThread(1);
PrintThread pt2 = new PrintThread(2);
pt0.start();
pt1.start();
pt2.start();
}}
private static Integer sflag=0; 改成 private volatile static Integer sflag=0;问题解决
呵呵,确实是可见性的问题,while实际上相当于自旋了。
之前一直不明白为什么死循环,想来想去,不管时间片怎么分,都不会死循环来着。
里层不执行,所以 都是count > 10,就死循环吧.