5

In effective java 2nd Edition Item 70 Josh Bloch explained about thread hostile classes

This class is not safe for concurrent use even if all method invocations are surrounded by external synchronization. Thread hostility usually results from modifying static data without synchronization

Can Someone explain me with example how it's impossible to achieve thread safety by external synchronization if the class modifies shared static data without internal synchronization?

3 Answers 3

8

The citation assumes the synchronization of every call to the class method on the same object instance. For example, consider the following class:

public class Test { private Set<String> set = new TreeSet<>(); public void add(String s) { set.add(s); } } 

While it's not thread-safe, you can safely call the add method this way:

public void safeAdd(Test t, String s) { synchronized(t) { t.add(s); } } 

If safeAdd is called from multiple threads with the same t, they will be mutually exclusive. If the different t is used, it's also fine as independent objects are updated.

However consider that we declare the set as static:

private static Set<String> set = new TreeSet<>(); 

This way even different Test objects access the shared collection. So in this case the synchronization on Test instances will not help as the same set may still be modified concurrently from different Test instances which may result in data loss, random exception, infinite loop or whatever. So such class would be thread-hostile.

Sign up to request clarification or add additional context in comments.

5 Comments

So now the only possible way to make this class thread safe is synchronizing it internally i.e. by making the add method as static synchronized which acquires lock on the class object itself right?
@ArghyaSadhu, well you still can synchronize externally on the class object itself, but that's ugly, because the method is non-static, thus it's not expected to modify global state in unsafe manner. The better alternative would be to use the concurrent-friendly data structure like ConcurrentSkipListSet.
@TagirValeev...Yes its possible since we have a concurrent friendly data structure available for us.I was wandering if there is any scenario where even synchronizing externally with class object wouldn't make this class thread safe
@ArghyaSadhu I think you are a bit confused on what Josh tried to deliver. That part simply describe the "thread-safetiness level", it is not about "if you do this then you will become certain level". e.g. it is NOT "if you access static variable, then you will become thread-hostile". There are always ways to make it thread-safe. What it means is: "thread-hostile code means it is not thread-safe even you externally synchronize on instance, which is usually caused by static var access" Hope you see the difference
@ArghyaSadhu, you can always create a single global lock and synchronize everything on it, making your application totally safe (though it would become essentially single-threaded).
2

Can Someone explain me with example how it's impossible to achieve thread safety by external synchronization if the class modifies shared static data without internal synchronization?

It's not impossible. If the class has methods that access global (i.e., static) data, then you can achieve thread-safety by synchronizing on a global lock.

But forcing the caller to synchronize threads on one global lock still is thread-hostile. A big global lock can be a serious bottleneck in a multi-threaded application. What the author wants you to do is design your class so that it would be sufficient for the client to use a separate lock for each instance of the class.

Comments

1

Perhaps a contrived example, but this class is impossible to synchronize externally, because the value is accessible from outside the class:

public class Example { public static int value; public void setValue(int newValue) { this.value = newValue; } } 

However you synchronize invocation of the setter, you can't guarantee that some other thread isn't changing value.

8 Comments

So if we do synchronize the setter method internally ...does it make the class thread safe?
What exact change are you thinking of when you say "synchronize internally"?
"impossible to synchronize externally, because the value is public" That sounds strange to me. It should be "synchronize externally does not make code thread-safe". And the reason has nothing to do with the value being public.
If I just add synchronized in the setter method signature or if I take a private lock object and synchronize the setter method using that lock object is what I am trying to mean by synchronize internally
@ArghyaSadhu that would not make it thread safe, because anything can access the value, irrespective of the lock: it's visible outside the class.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.