对不起,如果这是非常明显的或已在其他地方回答。我一直无法找到任何东西。我有以下代码:Java同步混淆
public class SimpleThread extends Thread {
public static Integer sharedVal = 0;
public SimpleThread() {
}
@Override
public void run() {
while(true) {
iterator();
}
}
public void theSleeper() {
System.out.println("Thread: " + this.getId() + " is going to sleep!");
try {
this.sleep(5000);
} catch(Exception e) {
}
}
public void iterator() {
synchronized(sharedVal) {
System.out.println("Iterating sharedVal in thread: " + this.getId());
sharedVal++;
System.out.println(sharedVal);
theSleeper();
System.out.println("Thread : " + getId() + " is done sleeping, trying to iterate again...");
}
}
}
我创建了这个SimpleThread类的两个实例,并执行run方法。我期望看到像这样的东西:线程9递增...线程9睡眠...(5秒后)线程10递增....线程10睡眠...。我期望这是因为我锁定了迭代器方法,以便一次只能有一个线程能够输入它。相反,两个线程都会增加,然后等待5秒钟。这永远重复。我在这里错过了什么,以便得到预期的行为?非常感谢!
编辑:我做了一个新的公共静态变量:public static Object theLock = new Object()。现在,在迭代器方法中,我确实同步了(theLock)。现在输出更像我所期望的那样,因为锁永远不会改变。但是,现在只有线程9进入该方法。看来,线程10正在挨饿,并且永远不会回合。这似乎很奇怪。这不只是几次,它总是只是线程9迭代和睡眠。我会认为这将是9,10,9,10。或者可能是一个随机分布像9,10,10,10,9,10,9,9,10等
编辑2:我看到什么是正在发生。线程9有锁。线程10尝试进入该功能,但被立即告知要等待。函数完成后,它可能仍然是线程9转。线程9然后获得锁,并且循环继续。线程10得到一个回合的时间窗口非常小,如果它确实得到了回合,它可能会挨饿9.也就是说,在iterator()中的synchronized块之后放置yield()看起来并没有使它更多公平。我阅读了关于该方法的评论,而调度器实际上可以忽略yield()。
自动装箱是魔鬼 –
哈哈哈,现在看来,这可能是有问题的! :) – user2045279