Reputation: 635
My java code looks like this:
class xHandler
{
private Channel _channel;
// Methods...
void init()
{
_channel = new Channel(...);
synchronized (_channel)
{
// Do some stuff here...e.g.
_channel.send("...");
}
}
}
In other files(threads) I create instances of Channel and send stuff with the use of the object, but only in the init method mentioned above I need it to be sync'ed and no other thread should open a channel and send something during this period.
FindBugs gives me a warning called: Method synchronizes on an updated field
This method synchronizes on an object referenced from a mutable field. This is unlikely to have useful semantics, since different threads may be synchronizing on different objects.
How can I get this issue right? Is it possible to trigger this issue easily with a simple test?
Upvotes: 2
Views: 431
Reputation: 22461
_channel = new Channel(...);
synchronized (_channel)
I need it to be sync'ed and no other thread should open a channel and send something during this period.
Seems like your code is not doing what you are thinking that it is doing. Since you are creating a new Channel
object per xHandler
instance, and acquiring this specific Channel
lock, two threads may run concurrently.
What you really need to do is either:
Channel
object that you want to sync for multiple xHandler
instances (Example: receive a instance of Channel
on xHandler
constructor and assign it to _channel
, remove the _channel = new Channel(...);
line and keep your sync code as it is).Channel.class
which will mean that two different instances of xHandler
will never be able to use any Channel
simultaneously.Example of sharing a specific Channel
for two different xHandlers:
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
}
}
Upvotes: 1
Reputation: 5681
You keep on creating a new lock every time the method is run. Thus you are negating the effects of locking. The lock will always allow new threads in because there will be no threads waiting on the newly created object (there could be every now and then through some race condition
). Each thread basically has its own lock (instead of a shared lock).
Move channel
outside of the method.
Upvotes: 2
Reputation: 178411
Note that synchronized
is acquiring lock on an object and not on a variable!
Each invokation of this method will have a lock on a different object, so the synchronized block in here is actually redundant, since you modify it when you enter init()
.
[so as the warning says, different threads are being synchronized on different objects].
What will happen if two threads will try to invoke init()
concurrently? Both of them might enter the critical section at the same time, and this is what you are warned about.
To solve it, you might want to declare _cahnnel
as final
, and initialize it in the constructor, and not init()
.
Upvotes: 3