代码片段 - 1
class RequestObject implements Runnable
{
private static Integer nRequests = 0;
@Override
public void run()
{
synchronized (nRequests)
{
nRequests++;
}
}
}
代码片段 - 2
public class Racer implements Runnable
{
public static Boolean won = false;
@Override
public void run()
{
synchronized (won)
{
if (!won)
won = true;
}
}
}
我在第一个代码片段中遇到了竞态条件。我明白这是因为我在一个不可变对象(类型为Integer)上获得了锁。
我写了第二个代码片段,它再次不受“Boolean”不可变的影响。但这次可以正常工作(没有输出运行时的竞态条件)。如果我正确理解了先前的问题的解决方案,下面是可能出错的一种方式。
- 线程1获取了一个对象的锁(假设是A)并指向了
won
- 线程2试图获取
won
所指向的对象的锁,然后进入A的等待队列 - 线程1进入同步块,验证A为false,并通过
won=true
创建一个新对象(假设为B),A认为它赢得了比赛。 - 'won'现在指向B。线程1释放了对象A上的锁(不再指向
won
) - 现在,处于对象A等待队列中的线程2被唤醒并获取了对象A的锁,该锁仍然是
false
(不可变的)。它现在进入同步块并假设自己也赢了,这是不正确的。
为什么第二个代码片段总是正常工作??
set
方法。Immutable 与final
无关。 - Multithreadersynchronized
语句而不会产生外部影响),因此该问题永远不会产生“意外”的结果。 - Hot Licks