同步对Immutable Integer对象的访问

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

class RequestObject implements Runnable
{
    private static Integer nRequests = 0;
    private static Object lock = new Object();

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

虽然第二个代码片段工作正常而没有引起任何竞争条件,但第一个代码片段不能成功同步对同一个类的不同实例(RequestObject)之间的静态数据成员的访问.有人可以对此有所了解吗?我想了解为什么第一种方法不起作用.

我最初的实现是第一个.后来我在/sf/answers/148428661/中看到了.

Jen*_*der 6

您不断创建新的Integer对象,然后对其进行同步,这至少会让人难以理解.所以你可以得到以下场景:

线程A获取当前值nRequests(假设为0)

线程B队列为相同的值(0)

线程A增加nRequests(值1)

线程C获取新值并在其上同步,增加它并释放值.

线程A放开监视器0

线程B在0上同步并将其增加到1,覆盖C的变化

使用第二种方法,您可以拥有一个每个人都必须同步的对象.这正是你想要的.


mer*_*ike 5

的实例Integer是不可变的,nRequests++因此创建一个新Integer对象来保存结果,并将其存储在nRequests. 该synchronized语句在对象上同步。因此,线程将在不同的对象上同步。是的,同一个对象上的同步块中可能只有一个线程同时存在,但是不同的线程可能同时在不同对象的同步块中......

同步访问静态状态的最简单方法是将其放入静态同步方法中:

static synchronized void increment() {
    nRequests++;
}
Run Code Online (Sandbox Code Playgroud)

这等效于以下同步块:

synchronized (RequestObject.class) {
    nRequests++;
}
Run Code Online (Sandbox Code Playgroud)

其中 RequestObject 是包含静态字段的类。