Java 方法在更新的字段上进行同步
我的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(
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
实例同步的特定Channel
对象(例如:在xHandler
构造函数上接收Channel
实例,并将其分配给\u Channel
,删除\u Channel=new Channel(…)
行并保持同步代码不变)Channel.class
上同步,这意味着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为提示,我编辑过,现在应该是正确的。