Reputation: 5775
I have a simple bean @Entity Message.java that has some normal properties. The life-cycle of that object is as follows
Instantiation of Message happens on Thread A, which is then enqueued into a blockingQueue
Another thread from a pool obtains that object and do some stuff with it and changes the state of Message, after that, the object enters again into the blockingQueue. This step is repeated until a condition makes it stop. Each time the object gets read/write is potentially from a different thread, but with the guarantee that only one thread at a time will be reading/writing to it.
Given that circumstances, do I need to synchronize the getters/setters ? Perhaps make the properties volatile ? or can I just leave without synchronization ?
Thanks and hope I could clarify what I am having here.
Upvotes: 18
Views: 15726
Reputation: 269897
No, you do not need to synchronize access to the object properties, or even use volatile
on the member variables.
All actions performed by a thread before it queues an object on a BlockingQueue
"happen-before" the object is dequeued. That means that any changes made by the first thread are visible to the second. This is common behavior for concurrent collections. See the last paragraph of the BlockingQueue
class documentation:
Memory consistency effects: As with other concurrent collections, actions in a thread prior to placing an object into a
BlockingQueue
happen-before actions subsequent to the access or removal of that element from theBlockingQueue
in another thread.
As long as the first thread doesn't make any modifications after queueing the object, it will be safe.
Upvotes: 33
Reputation: 45463
You don't need to do synchronization yourself, because the queue does it for you already.
Visibility is also guaranteed.
Upvotes: 4
Reputation: 489
It would sound like you could leave of the synchronized off the methods. The synchronized simply locks the object to allow only a single thread to access it. You've already handled that with the blocking queue.
Volatile would be good to use, as that would ensure that each thread has the latest version, instead of a thread local cache value.
Upvotes: 0
Reputation: 20895
If you're sure that only one thread at a time will access your object, then you don't need synchronisation.
However, you can ensure that by using the synchronized keyword: each time you want to access this object and be sure that no other thread is using the same instance, wrap you code in a synchronized block:
Message myMessage = // ...
synchronized (myMessage) {
// You're the only one to have access to this instance, do what you want
}
The synchronized block will acquire an implicit lock on the myMessage object. So, no other synchronized block will have access to the same instance until you leave this block.
Upvotes: 2