Visibility of mutable object under different locks in Java - java

mFeaute is a mutable object.
I want to know if the change of mFeature in setFeature(Feature feature) is visible to mFeature in useFeature(...) with a different explicit form of synchronized.
Thanks.
public class FeatureService {
private static Feature mFeature= null;
private final Object MUTEX = new Object();
...
static void setFeature(Feature feature){
// doSomething
synchronized (FeatureService.class){
mFeature = feature;
// doSomething
}
// doSomething
}
public void useFeature(...){
// doSomething
synchronized (MUTEX){
someFunction(mFeature);
// doSomething
}
// doSomething
}
}
}

The above code is suffering from a data race and hence is broken. You do not have a happens before edge between the write and the read of mfeature because different locks are used. You need to use the same lock instance for both reading and writing.

It is unclear what you are trying to synchronize on (ClassA and ObjectB are vague). In general, you want to synchronize on a single mutex when interacting with a given shared resource. Create an Object to serve as the mutex upon which you synchronize when accessing the internal mFeature.
public class FeatureService {
private static Feature mFeature= null;
private static final Object MUTEX = new Object();
...
static void setFeature(Feature feature){
synchronized (MUTEX){
mFeature = feature;
}
}
public void useFeature(...){
synchronized (MUTEX){
someFunction(mFeature);
}
}
}

Related

Some case-specific questions about multi-threading

Question 1.
If we consider the following class:
public class Test {
public static LinkedList<String> list;
}
How would you make getting/setting thread-safe for the variable 'list'?
I guess I could do something like this:
public class Test {
private static LinkedList<String> list;
public static synchronized LinkedList<String> getList() {
return new LinkedList<>(list);
}
public static synchronized void setList(LinkedList<String> data) {
list = new LinkedList<>(data);
}
}
Question 2.
But how thread-safe is this? Would I have to initialize a new list each time to ensure other copies don't affect the variable?
Question 3.
If we consider this instead:
public class Test {
private static LinkedList<String> list;
public static synchronized void ManipulateList() {
// do stuff to 'list'
}
public static synchronized void ChangeList() {
// do more stuff to 'list'
}
}
where both methods 'ManipulateList' and 'ChangeList' might add or remove variables to the same list
Is this thread-safe? Does this mean that if thread 1 is accessing 'ManipulateList' then thread 2 is not able to access 'ChangeList' until thread 1 finishes accessing 'ManipulateList'?
I'm just not sure if I'm understanding the effects correctly.
Question 1.
public static LinkedList<String> list;
How would you make getting/setting thread-safe for the variable
'list'?
Avoid global [mutable] state. Just get rid of it.
Question 2.
public class Test {
private static LinkedList<String> list;
public static synchronized LinkedList<String> getList() {
return new LinkedList<>(list);
}
public static synchronized void setList(LinkedList<String> data) {
list = new LinkedList<>(data);
}
}
But how thread-safe is this? Would I have to initialize a new list
each time to ensure other copies don't affect the variable?
(I am going to assume by this you mean Test.list not the passed in data which, due to the defects of the Java collection library, is mutable itself.
So you are always accessing the list with the same lock held. You are always copying the list when dealing with the outside world. The members of the list are immutable, so you don't need any deep copying. All good.
The method have the lock held over an expensive operation not involving the variable, so we should do better here.
public static synchronized LinkedList<String> getList() {
// The `LinkedList` list points to is never mutated after set.
LinkedList<String> local;
synchronized (Test.class) {
local = list;
}
return new LinkedList<>(local);
}
public static void setList(LinkedList<String> data) {
LinkedList<String> local = new LinkedList<>(data);
synchronized (Test.class) {
list = local;
}
}
In theory, even without the change the lock needn't be held continuously for the entire copy. As it is a public lock object (but naughty, but common) data could wait on it releasing the lock temporarily. Obviously not significant here, but in real world cases it may lead to strangeness.
Slightly more obscurely, list could be made volatile and the lock elided.
Question 3.
private static LinkedList<String> list;
public static synchronized void ManipulateList() {
// do stuff to 'list'
}
public static synchronized void ChangeList() {
// do more stuff to 'list'
}
Is this thread-safe? Does this mean that if thread 1 is accessing
'ManipulateList' then thread 2 is not able to access 'ChangeList'
until thread 1 finishes accessing 'ManipulateList'?
Yes. Other than there may be waits and one of the methods could call the other, perhaps indirectly.
General notes.
Remove global [mutable] state.
Try to avoid shared mutable object (keep shared object immutable and mutable objects unshared).
Reduce the amount of code and time that locks are held for.
Copy mutable inputs and outputs.
I guess I could do something like this:
This isn't thread safe.
Specifically, the setter:
public static synchronized void setList(LinkedList<String> data) {
list = new LinkedList<>(data);
}
does not enforce that data is accessed exclusively for the duration of the setList method. As such, other threads could modify the list during the implicit iteration.
The code in question 3 is fine with respect to updates to the list, because the fact the methods are synchronized means that the list is accessed mutually exclusively, and the effects of one method invocation are visible to subsequent invocations.
But it's not entirely safe, because nefarious code can acquire (and hold onto) the monitor of Test, which could lead to a deadlock.
You can fix this specific issue by having an explicit monitor that can only be acquired inside the class:
class Test {
private final Object obj = new Object();
public static void ManipulateList() {
synchronized (obj) { ... }
}
public static void ChangeList() {
synchronized (obj) { ... }
}
}
Anything that subclasses your Test class could break your synchronization scheme because subclasses could directly access the list without the method-synchronization - either by subclassing your Test class or through reflection.
public class MyTestClass extends Test {
// blah...
public static changeTheList() {
this.list.add("Bypasses synchronization through direct access to the list.");
}
}
A better solution for synchronization is to initialize your list with a synchronized wrapper, like this:
public class Test {
private static LinkedList<String> list = Collections.synchronizedList(new LinkedList<>());
public static synchronized LinkedList<String> getList() {
return list;
}
public static synchronized void setList(LinkedList<String> newList) {
list = newList;
}
}
In the second snippet, you can now safely sub-class your Test class and access the list in a thread-safe manner because the list itself is synchronized.
You other option is to mark your Test class as final but you would still need to fix your implementation (you re-initialize the list in your getter's & setter's which is not a good idea).
Also -- I might suggest you look at some tutorials regarding synchronization -- a couple of suggestions:
https://www.baeldung.com/java-synchronized-collections
https://howtodoinjava.com/java/collections/arraylist/synchronize-arraylist/

Thread safe access to private field

So I have the following scenario (can't share the actual code, but it would be something like this):
public class Test
{
private Object obj;
public void init()
{
service.registerListener(new InnerTest());
}
public void readObj()
{
// read obj here
}
private class InnerTest implements Listener
{
public synchronized void updateObj()
{
Test.this.obj = new Object();
// change the obj
}
}
}
The InnerTest class is registered as listener in a service. That Service is running in one thread the calls to readObj() are made from a different thread, hence my question, to ensure consistency of the obj is it enough to make the UpdateObj() method synchronized?
I would suggest using another object as a lock to ensure that the class only blocks when the obj is accessed:
public class Test
{
private final Object lock = new Object();
private Object obj;
public void init()
{
service.registerListener(new InnerTest());
}
public void readObj()
{
synchronized(lock){
// read obj here
}
}
private class InnerTest implements Listener
{
public void updateObj()
{
synchronized(Test.this.lock){
Test.this.obj = new Object();
// change the obj
}
}
}
}
Then use that lock in all methods that need to have consistent access to obj. In your current example the readObj and updateObj methods.
Also as stated in the comments, using synchronized on the method level in your InnerTest class, will not really work as you probably intended. That is, because synchronized methods will use a synchronized block on the this variable. Which just blocks your InnerTest class. But not the outer Test class.

How class level lock is acquired

public synchronized int getCountOne() {
return count++;
}
Like in above code synchronizing on the method is functionally equivalent to having a synchronized (this) block around the body of the method. The object "this" doesn't become locked, rather the object "this" is used as the mutex and the body is prevented from executing concurrently with other code sections also synchronized on "this."
On similar grounds what is used as a mutex when we acquire a class level lock.As in if we have a function
public static synchronized int getCountTwo() {
return count++;
}
obviously two threads can simultaneously obtain locks on getCountOne(object level lock) and getCountTwo(class level lock). So as getCountOne is analogous to
public int getCountOne() {
synchronized(this) {
return count++;
}
}
is there an equivalent of getCountTwo? If no what criteria is used to obtain a Class level lock?
On similar grounds what is used as a mutex when we acquire a class level lock
The class object itself will be used as mutex. The equivalent synchronized block for your static synchronized method will look like:
public static int getCountTwo() {
synchronized(ClassName.class) {
return count++;
}
}
ClassName is the name of the class containing that method.
See JLS Section §8.4.3.6:
A synchronized method acquires a monitor (§17.1) before it executes.
For a class (static) method, the monitor associated with the Class
object for the method's class is used.
For an instance method, the monitor associated with this (the object
for which the method was invoked) is used.
Emphasis mine.
Object level locking:
Object level locking is mechanism when you want to synchronize a non-static method or non-static code block such that only one thread will be able to execute the code block on given instance of the class. This should always be done to make instance level data thread safe. This can be done as below :
public class DemoClass
{
public synchronized void demoMethod(){}
}
or
public class DemoClass
{
public void demoMethod(){
synchronized (this)
{
//other thread safe code
}
}
}
or
public class DemoClass
{
private final Object lock = new Object();
public void demoMethod(){
synchronized (lock)
{
//other thread safe code
}
}
Class level locking:
Class level locking prevents multiple threads to enter in synchronized block in any of all available instances on runtime. This means if in runtime there are 100 instances of DemoClass, then only one thread will be able to execute demoMethod() in any one of instance at a time, and all other instances will be locked for other threads. This should always be done to make static data thread safe.
public class DemoClass
{
public synchronized static void demoMethod(){}
}
or
public class DemoClass
{
public void demoMethod(){
synchronized (DemoClass.class)
{
//other thread safe code
}
}
}
or
public class DemoClass
{
private final static Object lock = new Object();
public void demoMethod(){
synchronized (lock)
{
//other thread safe code
}
}
}

Java synchronized and static synchronized method accessing static field

What would be the behaviour of the following program where static synchronized method and instance synchronized method is trying to access static field of same class in different threads? Will any thread get blocked? Its very confusing.
class MyClass
{
public static int i = 5;
public synchronized void m1()
{
System.out.println(i); //uses static field i of MyClass
//T1 is executing this method
}
public static synchronized void m3()
{
//T2 will be able to call this method on same object lock while it is using
//static field i???
System.out.println(i);//uses static field i of MyClass
}
}
Synchronized instance methods are equivalent of
public void m1() {
synchronized(this) {
...
}
}
(well, they are not exactly the same, but the answer to your question does not suffer from that difference).
Synchronized static methods are synchronized on the class:
public void m2() {
synchronized(MyClass.class) {
...
}
}
As you can see, two block are synchronized on difference objects: m1 is synchronized on the instance it is called on, and m2 is synchronized on the instance of Class<MyClass> which represents your class in JVM. So those two methods can be called without blocking each other.
You are always synchronizing on an object.
Funciton m1 synchronizes on an instance of an object on which it is called.
Function m3 synchronizes on the class itself.
m1 could be written as:
public void m1()
{
synchronized(this) {
System.out.println(i); //uses static field i of MyClass
//T1 is executing this method
}
}
Therefore you are synchronizing on two different objects and these two methods can acces any global variable concurrently.
Your sample code looks good.
Best way to assure synchronization of static variables according to me is. As lock object is not accessible outside your Class. See below.
public class MyClass
{
private static int i = 0;
private static final Object lockObject = new Object();
public void m1() {
synchronized (lockObject ) {
//Use you static var
}
}
public void m3() {
synchronized (lockObject ) {
//Use you static var
}
}
}
The method m1 and m3 can be executed independently.
Because as you already said static synchronized is on the object. Therefore the same as synchronize(MyClass.class).
synchronized are instance wide usable. So it is only blocked for the instances. It would be the same as using:
MyClass myClass = new MyClass();
synchronize (myClass)
{
.....
}
Java does not have any synchronization controls that relate to accessing static fields.
If you make your methods empty, the synchronization will be exactly the same.
Specifically, as long as any thread is executing any synchronized static method in that type, all other threads that call synchronized static methods will wait for them to finish, so that at most one synchronized static method will be executing at once.

What is the correct way to synchronize a shared, static object in Java?

This is a question concerning what is the proper way to synchronize a shared object in java. One caveat is that the object that I want to share must be accessed from static methods. My question is, If I synchronize on a static field, does that lock the class the field belongs to similar to the way a synchronized static method would? Or, will this only lock the field itself?
In my specific example I am asking: Will calling PayloadService.getPayload() or PayloadService.setPayload() lock PayloadService.payload? Or will it lock the entire PayloadService class?
public class PayloadService extends Service {
private static PayloadDTO payload = new PayloadDTO();
public static void setPayload(PayloadDTO payload){
synchronized(PayloadService.payload){
PayloadService.payload = payload;
}
}
public static PayloadDTO getPayload() {
synchronized(PayloadService.payload){
return PayloadService.payload ;
}
}
...
Is this a correct/acceptable approach ?
In my example the PayloadService is a separate thread, updating the payload object at regular intervals - other threads need to call PayloadService.getPayload() at random intervals to get the latest data and I need to make sure that they don't lock the PayloadService from carrying out its timer task
Based on the responses, I refactored to the following:
public class PayloadHolder {
private static PayloadHolder holder;
private static PayloadDTO payload;
private PayloadHolder(){
}
public static synchronized PayloadHolder getInstance(){
if(holder == null){
holder = new PayloadHolder();
}
return holder;
}
public static synchronized void initPayload(){
PayloadHolder.payload = new PayloadDTO();
}
public static synchronized PayloadDTO getPayload() {
return payload;
}
public static synchronized void setPayload(PayloadDTO p) {
PayloadHolder.payload = p;
}
}
public class PayloadService extends Service {
private static PayloadHolder payloadHolder = PayloadHolder.getInstance();
public static void initPayload(){
PayloadHolder.initPayload();
}
public static void setPayload(PayloadDTO payload){
PayloadHolder.setPayload(payload);
}
public static PayloadDTO getPayload() {
return PayloadHolder.getPayload();
}
...
Is this approach legitimate? I am also curious if it is better to do it this way or using the AtomicReference approach mentioned by Hardcoded ...?
- I am keeping an instance of PayloadHolder on PayloadService simply to keep a reference to the PayloadHolder class active in the jvm for as long as the PayloadService is running.
Your code should look like this:
public static void setPayload(PayloadDTO payload){
synchronized(PayloadService.class){
PayloadService.payload = payload;
}
}
public static PayloadDTO getPayload() {
synchronized(PayloadService.class){
return PayloadService.payload ;
}
}
Your original code wouldn't have worked even if the methods weren't static. The reason being is you were synchronizing on the payload instance that you were changing.
Update, a response to johnrock comment:
Locking the whole class is only a problem if you have other synchronized static blocks that you want to run currently. If you want to have multiple independent locked section then I suggest you do something like this:
public static final Object myLock = new Object();
public static void setPayload(PayloadDTO payload){
synchronized(myLock){
PayloadService.payload = payload;
}
}
public static PayloadDTO getPayload() {
synchronized(myLock){
return PayloadService.payload ;
}
}
Or, if you require a more complex concurrency pattern look at java.util.concurrent which has many pre-built classes to aid you.
You could, as mentioned in other posts, synchronize on the class or on an explicit monitor.
There are 2 other ways, if we assume that your are using the sychnronize only for thread-safe getting and setting of the property: volatile and AtomicReference.
volatile
The volatile keyword will make access to the variable atomic, meaning that reading and assigning the variable won't be optimized by the CPUs local registers and are done atomically.
AtomicReference
The AtomicReference is a special class at the java.util.concurrent.atomic package, which allows atomic access to a variable-like reference. It is very similiar to volatile, but gives you some additional atomic operations, like compareAndSet.
Example:
public class PayloadService extends Service {
private static final AtomicReference<PayloadDTO> payload
= new AtomicReference<PayloadDTO>(new PayloadDTO());
public static void setPayload(PayloadDTO payload){
PayloadService.payload.set(payload);
}
public static PayloadDTO getPayload() {
return PayloadService.payload.get ;
}
Edit:
Your Holder seems quite confused, since you are instantiating classes only to call static Methods. A try to get it fixed with AtomicReference:
public class PayloadHolder {
private static AtomicReference<PayloadHolder> holder = new AtomicReference<PayloadHolder();
//This should be fetched through the holder instance, so no static
private AtomicReference<PayloadDTO> payload = new AtomicReference<PayloadDTO>();
private PayloadHolder(){
}
public static PayloadHolder getInstance(){
PayloadHolder instance = holder.get();
//Check if there's already an instance
if(instance == null){
//Try to set a new PayloadHolder - if no one set it already.
holder.compareAndSet(null, new PayloadHolder());
instance = holder.get();
}
return instance;
}
public void initPayload(){
payload.set(new PayloadDTO());
//Alternative to prevent a second init:
//payload.compareAndSet(null, new PayloadDTO());
}
public PayloadDTO getPayload() {
return payload.get;
}
public void setPayload(PayloadDTO p) {
payload.set(p);
}
}
public class PayloadService extends Service {
private final PayloadHolder payloadHolder = PayloadHolder.getInstance();
public void initPayload(){
payloadHolder.initPayload();
}
public void setPayload(PayloadDTO payload){
payloadHolder.setPayload(payload);
}
public PayloadDTO getPayload() {
return payloadHolder.getPayload();
}
}
My question is, If I synchronize on a static field, does that lock the class the field belongs to similar to the way a synchronized static method would? Or, will this only lock the field itself?
No, it just lock in the object itself ( the class attribute not the whole class )
Is this a correct/acceptable approach ?
You could probably take a look at the java.util.concurrent.lock package.
I don't really like synchronizing on a class attribute, but I guess that's just a matter of teste.
Synchronize on another static object that does not change:
public class PayloadService extends Service {
private static PayloadDTO payload = new PayloadDTO();
private static final Object lock = new Object();
public static void setPayload(PayloadDTO payload){
synchronized(lock){
PayloadService.payload = payload;
}
}
public static PayloadDTO getPayload() {
synchronized(lock){
return PayloadService.payload ;
}
}
Is this a correct/acceptable approach ?
No, the reason for this is that you should never synchronize on an variable/field that can change its value. That is, when you synchronize on PayloadService.payload and set a new PayloadService.payload, then you are violating a golden rule of synchronization.
You should either synchronize on the class instance or create some arbitrary private static final Object lock = new Object() and synchronize on that. You will have the same effect as synchronizing on the class.
There is a major part of functionality in this class which isn't posted which contributes to whether or not this approach is thread-safe: how do you access the PayloadDTO instance from the other parts of this class where it is used?
If you are providing methods which could swap in another instance for payload while another thread is running code which uses the payload object, then this is not thread safe.
For example if you have a method execute() which does the main work of this class and invokes methods on payload, you need to make sure that one thread cannot change the payload instance with the setter method while another thread is busy running execute().
In short, when you have shared state, you need to synchronize on all read and write operations on the state.
Personally I don't understand this approach and would never take it - providing static methods to allow other threads to re-configure a class smells like a violation of separation of concerns.

Categories