抱歉,如果这非常明显或已在其他地方得到回答。我什么都没找到。我有以下代码:
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 等。
EDIT2:我知道现在发生了什么。线程 9 有锁。线程 10 尝试进入函数,但立即被告知等待。函数完成后,可能仍是 Thread 9s 轮回。然后线程 9 重新获取锁,然后循环继续。线程 10 获得一个回合的时间窗口非常小,如果它确实获得了一个回合,它可能会饿死 9。话虽如此,将 yield() 放在 iterator() 中的同步块之后似乎并没有使它更多公平的。我阅读了有关该方法的注释,调度程序实际上可以忽略 yield()。