很抱歉,如果这是非常明显的,或者已经在其他地方得到解答。我什么都找不到。我有以下代码:
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秒钟。这将永远重复。我在这里想念什么,以便得到预期的行为?非常感谢!
编辑:我做了一个新的公共静态变量:公共静态对象theLock = new Object()。现在,在迭代器方法中,我进行了sync(theLock)。现在的输出比我预期的要多,因为锁定永远不会改变。但是,现在只有线程9才能进入该方法。线程10似乎饿了,再也没有转过身。这似乎很奇怪。这不仅是几次,而且总是线程9不断迭代和休眠。我认为应该是9、10、9、10,或者是9、10、10、10、9、10、9、9、10等随机分布。
EDIT2:我知道现在发生了什么。线程9具有锁。线程10尝试进入该函数,但立即被告知等待。函数完成后,可能仍是线程9s转动。然后线程9重新获得该锁,并且循环继续。线程10进行转弯的时间窗口非常小,如果确实转弯,则可能会饿死9。也就是说,将yield()放在iterator()中的同步块之后似乎并没有使它变多。公平。我阅读了有关该方法的注释,并且调度程序实际上可以忽略yield()。
您的问题出在这里:
sharedVal++;
该行,由于自动装箱转换为:
sharedVal = Integer.valueOf(sharedVal.intValue() + 1);
Integer
每次运行都会创建一个新对象,因此每次访问该synchronized
块时,它都会锁定一个不同的值。
使用专用对象进行同步:
private final static Object LOCK = new Object();
然后将您的同步更改为使用synchronized (LOCK) {...
。
(您也可以使用getClass()
锁定,但是我个人不希望将锁定对象公开。)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句