Java 同步对不可变整数对象的访问
代码片段-1Java 同步对不可变整数对象的访问,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
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
这是一个不同的问题。“请把它变成一个新问题。”詹绍德,完成了。