方法在更新的字段上同步

时间:2012-03-14 14:04:48

标签: java

我的java代码如下所示:

class xHandler
{
    private Channel _channel;

    // Methods...

    void init()
    {
        _channel = new Channel(...);

        synchronized (_channel)
        {
            // Do some stuff here...e.g.
            _channel.send("...");
        }
    }
}

在其他文件(线程)中我创建了Channel的实例并使用该对象发送了东西,但是只有在上面提到的init方法中我需要它进行同步,没有其他线程应该打开一个通道并发送在此期间的事情。

FindBugs给我一个警告:方法在更新的字段上同步

此方法在从可变字段引用的对象上进行同步。 这不太可能具有有用的语义,因为不同的线程可能在不同的对象上同步。

我怎样才能解决这个问题?是否可以通过简单的测试轻松触发此问题?

3 个答案:

答案 0 :(得分:3)

请注意synchronized正在获取对象的锁定而不是变量!

此方法的每次调用都会锁定另一个对象,因此此处的synchronized块实际上是多余的,因为您在输入init()时会对其进行修改。 [正如警告所说,不同的线程正在不同的对象上同步]。

如果两个线程同时尝试调用init()会发生什么?他们两个可能同时进入临界区,这就是你被警告的内容。

要解决此问题,您可能需要将_cahnnel声明为final,并在构造函数中初始化它,而不是init()

答案 1 :(得分:2)

每次运行方法时,您都会继续创建新锁。因此,你否定了锁定的影响。锁将始终允许新线程进入,因为没有线程在新创建的对象上等待(可能偶尔会有一些race condition)。每个线程基本上都有自己的锁(而不是共享锁)。

channel移到方法之外。

答案 2 :(得分:1)

_channel = new Channel(...);
synchronized (_channel)
  

我需要它同步,没有其他线程应该打开一个频道和   在此期间发送一些东西。

好像你的代码没有按照你的想法去做。由于您要为每个Channel实例创建一个新的xHandler对象,并获取此特定的Channel锁,因此可以同时运行两个线程。

  1. xHandler实例1创建了Channel实例1并获取了它的锁
  2. xHandler实例2创建了Channel实例2并获取了它的锁
  3. 两者同时运行
  4. 你真正需要做的是:

    1. 共享要为多个Channel实例同步的特定xHandler对象(示例:在Channel构造函数上接收xHandler的实例,并将其分配给{{ 1}},删除_channel行,并保持同步代码原样。)
    2. _channel = new Channel(...);上同步,这意味着Channel.class的两个不同实例永远无法同时使用任何xHandler
    3. 为两个不同的xHandler共享特定Channel的示例:

      Channel