Java 方法在更新的字段上进行同步

Java 方法在更新的字段上进行同步,java,Java,我的java代码如下所示: class xHandler { private Channel _channel; // Methods... void init() { _channel = new Channel(...); synchronized (_channel) { // Do some stuff here...e.g. _channel.send(

我的java代码如下所示:

class xHandler
{
    private Channel _channel;

    // Methods...

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

        synchronized (_channel)
        {
            // Do some stuff here...e.g.
            _channel.send("...");
        }
    }
}
在其他文件(线程)中,我使用对象创建通道实例并发送内容,但仅在上面提到的init方法中,我需要同步它,在此期间,其他线程不应打开通道并发送内容

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

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


我如何才能正确处理这个问题?是否可以通过简单的测试轻松触发此问题?

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

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

如果两个线程同时尝试调用
init()
,会发生什么情况?它们可能同时进入临界区,这就是警告您的


要解决这个问题,您可能需要将
\u cahnnel
声明为
final
,并在构造函数中初始化它,而不是
init()
每次运行该方法时都要继续创建一个新锁。因此,您正在否定锁定的效果。锁将始终允许新线程进入,因为在新创建的对象上不会有线程等待(可能偶尔会有一些
争用条件
)。每个线程基本上都有自己的锁(而不是共享锁)

频道
移到方法之外

_channel = new Channel(...);
synchronized (_channel)
我需要它是同步的,没有其他线程应该打开一个通道和 在此期间发送一些内容

似乎您的代码没有做您认为它正在做的事情。由于您正在为每个
xHandler
实例创建一个新的
Channel
对象,并获取这个特定的
Channel
锁,因此两个线程可能同时运行

  • xHandler实例1创建通道实例1并获取其锁
  • xHandler实例2创建通道实例2并获取其锁
  • 两者同时运行
  • 您真正需要做的是:

  • 共享要为多个
    xHandler
    实例同步的特定
    Channel
    对象(例如:在
    xHandler
    构造函数上接收
    Channel
    实例,并将其分配给
    \u Channel
    ,删除
    \u Channel=new Channel(…)
    行并保持同步代码不变)
  • Channel.class
    上同步,这意味着
    xHandler
    的两个不同实例将永远无法同时使用任何
    频道
  • 为两个不同的XHandler共享特定的
    频道的示例:

    class xHandler
    {
        private final Channel _channel;
    
        public xHandler(Channel channel)
        {
            this._channel = channel  
        }
    
        // Methods...
    
        void init()
        {           
            synchronized (_channel)
            {
                // Do some stuff here...e.g.
                _channel.send("...");
            }
        }
    
                public static void main(String[] args) 
                {
                    Channel myChannel = new Channel(...);
                    xHandler xHand1 = new xHandler(myChannel);
                    xHandler xHand2 = new xHandler(myChannel);
                    // Code to create / start your threads. 
                    // xHand1 and xHand2 will not use myChannel simultaneously  
                }
    
    }
    

    您的代码无效-无法在
    init
    方法中声明字段。。。你是说这是一个简单的赋值吗?可变字段意味着私有通道\u通道不是最终的。试着将场地设置为最终场地;Thx Jon Skeet为提示,我编辑过,现在应该是正确的。