对不起,如果这是非常明显或已在其他地方回答.我找不到任何东西.我有以下代码:
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().现在,在迭代器方法中,我做了synchronized(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().