Java对象赋值和锁定

18 浏览
0 Comments

Java对象赋值和锁定

考虑以下代码片段:

 Object bar1 = new ... ; 
 Object bar2 = new ... ; 
 Object foo = (bar1 或 bar2) ; 

现在,程序中的 foo 在不同的时间可能是 bar1 或 bar2。我只是想确认 synchronized(foo) 会锁定对应的 bar1 或 bar2。考虑到 Java 中对象不会被复制,这似乎是最有可能的情景。这样理解正确吗?

0
0 Comments

Java对象赋值和锁定问题的出现原因是因为在使用`synchronized`关键字时,实际上是在锁定对象的底层对象,而不是引用本身。

每个对象都有一个关联的监视器,在使用`synchronized`时,锁定的就是这个监视器。根据这里的说明:

在Java虚拟机中,每个对象和类都与一个监视器相关联。对于对象,关联的监视器保护对象的实例变量。对于类,监视器保护类的类变量。

解决这个问题的方法是将锁定操作放在正确的位置。如果要锁定对象的引用,而不是底层的对象,可以使用一个额外的对象作为锁定对象。这样可以避免混淆和意外的结果。

示例代码如下:

public class MyClass {
    private final Object lock = new Object();
    private SomeObject obj;
    public void setObj(SomeObject newObj) {
        synchronized (lock) {
            obj = newObj;
        }
    }
    public SomeObject getObj() {
        synchronized (lock) {
            return obj;
        }
    }
}

在上面的示例中,我们使用了一个额外的对象`lock`作为锁定对象。在设置和获取`obj`引用时,我们都使用了`synchronized`关键字,并将锁定操作放在了`lock`对象上。

通过这种方式,我们可以确保对`obj`引用的操作是线程安全的,避免了因为锁定底层对象而导致的问题。

总结起来,Java对象赋值和锁定问题的出现是因为`synchronized`关键字锁定的是对象的底层对象而不是引用本身。为了解决这个问题,可以使用一个额外的对象作为锁定对象来确保线程安全。

0
0 Comments

Java对象赋值和锁定问题是因为在多线程环境下,当一个对象被赋值给另一个对象时,可能会导致不同的线程看到不同的锁。为了解决这个问题,建议将对象声明为final,避免对象的引用发生变化。以下是一种可能导致问题的示例代码:

Object foo = bar1;
synchronized(foo) {
   foo = bar2;
}

上述代码中,线程首先将变量foo指向bar1对象,然后在synchronized块中将foo的引用改变为bar2对象。这种情况下,不同的线程可能会看到不同的锁对象,导致线程不同步的问题。

为了解决这个问题,可以将foo对象声明为final,这样它的引用就不能再被修改。这样,所有的线程都将看到同一个锁对象,确保线程同步。

参考链接:Locking on a mutable object - Why is it considered a bad practice?

0
0 Comments

Java对象赋值和锁定的问题是由于以下原因引起的:

在代码中,将一个对象赋值给另一个对象,并使用synchronized关键字对其中一个对象进行锁定。例如:

Object bar1 = new Object();
Object foo = bar1;
synchronized(foo) {
    ...
}

这样会在foo==bar1上加锁。

然而,这是一个奇怪且容易出错的构造。举个例子:

  • 线程1进入你的方法,此时foo == bar1
  • 线程1进入同步块,并对bar1加锁
  • 线程2进入你的方法,此时foo == bar2
  • 线程2进入同步块,并对bar2加锁

现在,你有两个线程同时运行同步块。我真的找不到你可能希望这样做的原因。如果确实有这样的需求,那么该代码块可能不应该被同步,并且应该使用不同的锁策略。

一般来说,除了final字段外,使用其他任何对象进行同步都是一个坏主意。如果bar1bar2需要同步,那么应该在内部进行同步。

详见这个相关帖子

解决方法是使用final字段进行同步,或者在需要同步的对象内部进行同步操作。

0