不可变对象的同步(在java中)

Abh*_*hav 5 java multithreading synchronization

代码段 - 1

class RequestObject implements Runnable
{
    private static Integer nRequests = 0;

    @Override
    public void run()
    {       
        synchronized (nRequests)
        {
            nRequests++;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

代码段 - 2

public class Racer implements Runnable
{
    public static Boolean won = false;    

    @Override
    public void run()
    {
        synchronized (won)
        {
            if (!won)
            won = true;
        }
    }        
}
Run Code Online (Sandbox Code Playgroud)

我在第一个代码片段中遇到了竞争条件.我明白这是因为我在一个不可变对象(Integer类型)上获得了一个锁.

我写了第二个代码片段,它再次不受'布尔'不可变的影响.但是这样可行(输出运行中不显示竞争条件).如果我已正确理解上一个问题的解决方案,则以下是一种可能出错的方法

  1. 线程1获取对象(例如A)所指向的锁定 won
  2. 线程2现在试图锁定指向的对象won并进入A的等待队列
  3. 线程1进入同步块,验证A是假并通过说won = true(A认为它赢得了比赛)创建一个新对象(比如说B ).
  4. 'won'现在指向B.线程1释放对象A上的锁(不再指向won)
  5. 现在,在对象A的等待队列中的线程2被唤醒并获得对象A的锁定,这仍然是false(不可变的).它现在进入同步块并假设它也赢了,这是不正确的.

为什么第二个代码段始终正常工作?

Mar*_*nik 7

    synchronized (won)
    {
        if (!won)
        won = true;
    }
Run Code Online (Sandbox Code Playgroud)

在这里你有一个瞬态竞争条件,你没有注意到它,因为它在第一次执行该run方法后就消失了.之后,won变量不断指向相同的Boolean表示实例true,因此可以正确地用作互斥锁.

这并不是说您应该在实际项目中编写此类代码.应将所有锁定对象分配给final变量,以确保它们永远不会更改.