Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 同步对不可变整数对象的访问_Java_Multithreading_Synchronization - Fatal编程技术网

Java 同步对不可变整数对象的访问

Java 同步对不可变整数对象的访问,java,multithreading,synchronization,Java,Multithreading,Synchronization,代码片段-1 class RequestObject implements Runnable { private static Integer nRequests = 0; @Override public void run() { synchronized (nRequests) { nRequests++; } } } 代码片段-2 class RequestOb

代码片段-1

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

    @Override
    public void run()
    {       
        synchronized (nRequests)
        {
            nRequests++;
        }
    }
}
代码片段-2

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

    @Override
    public void run()
    {       
        synchronized (lock)
        {
            nRequests++;
        }
    }
}
虽然第二个代码段工作正常,没有引起任何争用条件,但第一个代码段无法成功地在同一类(RequestObject)的不同实例之间同步对静态数据成员的访问。谁能再多解释一下这件事。我想了解为什么第一种方法不起作用


我最初的实现是第一个。后来我在中看到了。

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

同步静态访问的最简单方法是将其置于静态同步方法中:

static synchronized void increment() {
    nRequests++;
}
这相当于以下同步块:

synchronized (RequestObject.class) {
    nRequests++;
}

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

问题在于
Integer
类在java中是不可变的。因此,每个线程在不同的对象上同步,因为
nRequests++
在每次调用时都会创建一个新对象


在第二种情况下,
lock
对象对于每个实例都是相同的,并且成功地序列化了线程对
nRequests
变量的访问。

您不断地创建新的整数对象,然后在这些对象上进行同步,这至少让您觉得非常困惑。因此,您可以得到以下场景:

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

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

线程A增加
nRequests
(到值1)

线程C获取新值并对其进行同步,增加该值并释放该值

线程A释放0上的监视器

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


对于第二种方法,您有一个每个人都必须同步的对象。这正是您想要的。

因为
Integer
是不可变的。递增它并不是做你认为的事情。也不要使用整数,使用
int
这是一个不同的问题。“请把它变成一个新问题。”詹绍德,完成了。