I am reading "Java Concurrency in Practice" and this case is a little bit unclear to me. Why is this code ThreadSafe?
#ThreadSafe
public class ListHelper<E> {
public List<E> list =
Collections.synchronizedList(new ArrayList<E>());
...
public boolean putIfAbsent(E x) {
synchronized (list) {
boolean absent = !list.contains(x);
if (absent)
} }
}
we lock instance of SynchronizedList list but inside that used inner object
final Object mutex; // Object on which to synchronize
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
We still have locks on two different objects. Why is it safe?
Good question.
You have to follow the whole chain of when mutex is assigned.
If not specified explicitly when calling Collections.synchronizedList as a second argument it will be the list itself.
Deep down you eventully find this:
mutex = this;
Related
We're building cache stores in our app backed by memory, file, and remote services. Want to avoid explicit synchronization to keep the stores simple while using decorators for behavioral concerns like blocking.
Here's a simple cache, this is just an example!
import java.util.HashMap;
public class SimpleCache {
private HashMap<String,Object> store;
private final BlockingCacheDecorator decorator;
public SimpleCache(){
store = new HashMap<String,Object>();
decorator = new BlockingCacheDecorator(this);
}
//is NOT called directly, always uses decorator
public Object get(String key){
return store.get(key);
}
//is NOT called directly, always uses decorator
public void set(String key, Object value){
store.put(key, value);
}
//is NOT called directly, always uses decorator
public boolean isKeyStale(String key){
return !(store.containsKey(key));
}
//is NOT called directly, always uses decorator
public void refreshKey(String key){
store.put(key, new Object());
}
public BlockingCacheDecorator getDecorator(){
return decorator;
}
}
getDecorator() returns a decorator providing synchronization for get() and set(), while isKeyStale() and refreshKey() allows the decorator to check if a key should be refreshed without knowing why or how. I got the idea for a synchronizing decorator from here.
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class BlockingCacheDecorator {
private SimpleCache delegate;
private final ReentrantReadWriteLock lock;
public BlockingCacheDecorator(SimpleCache cache){
delegate = cache;
lock = new ReentrantReadWriteLock();
}
public Object get(String key){
validateKey(key);
lockForReading();
try{
return delegate.get(key);
}finally{ readUnlocked(); }
}
public void setKey(String key, Object value){
lockForWriting();
try{
delegate.set(key,value);
}finally{ writeUnlocked(); }
}
protected void validateKey(String key){
if(delegate.isKeyStale(key)){
try{
lockForWriting();
if(delegate.isKeyStale(key))
delegate.refreshKey(key);
}finally{ writeUnlocked(); }
}
}
protected void lockForReading(){
lock.readLock().lock();
}
protected void readUnlocked(){
lock.readLock().unlock();
}
protected void lockForWriting(){
lock.writeLock().lock();
}
protected void writeUnlocked(){
lock.writeLock().unlock();
}
}
Questions:
Assuming SimpleCache is only ever used via its decorator, is the code thread-safe?
Is it bad practice for ReadWriteLock to be declared outside the class being synchronized? SimpleCache.getDecorator() ensures a 1-to-1 mapping between cache and decorator instances, so I'm assuming this is ok.
Is this code thread-safe?
Yes. Assuming that the instance of the decorated SimpleCache is not passed about.
Is it bad practice for ReadWriteLock to be declared outside the class being synchronized? SimpleCache.getDecorator() ensures a 1-to-1 mapping between cache and decorator instances, so I'm assuming this is ok.
No. Although it is also worth noting that as discussed in comments, BlockingCacheDecorator would usually implement a Cache interface.
In its current form the code is trivially non-threadsafe, as there's nothing preventing a caller from calling methods of SimpleCache directly, or indeed pass the same SimpleCache instance to multiple decorators, causing even more mayhem.
If you promise never to do that, it is technically thread-safe, but we all know how much those promises are worth.
If the aim is to be able to use different implementations of underlying caches, I'd create a CacheFactory interface:
interface CacheFactory {
Cache newCache();
}
A sample implementation of the factory:
class SimpleCacheFactory implements CacheFactory {
private final String cacheName; //example cache parameter
public SimpleCacheFactory( String cacheName ) {
this.cacheName = cacheName;
}
public Cache newCache() {
return new SimpleCache( cacheName );
}
}
And finally your delegate class:
public class BlockingCacheDecorator {
private final Cache delegate;
private final ReentrantReadWriteLock lock;
public BlockingCacheDecorator(CacheFactory factory){
delegate = factory.newCache();
lock = new ReentrantReadWriteLock();
}
//rest of the code stays the same
}
This way there's a much stronger guarantee that your Cache instances won't be inadvertently reused or accessed by an external agent. (That is, unless the factory is deliberately mis-implemented, but at least your intention not to reuse Cache instances is clear.)
Note: you can also use an anonymous inner class (or possibly a closure) to provide the factory implementation.
Suppose, I have static setter and getter like:
private static List<String> result = new ArrayList<String>();
public static void setResult(String result) {
result.add(result);
}
public static List<String> getResult() {
return result;
}
public static void clearResult() {
result.clear();
}
I want to know if setResult() is operating from a thread and getResult() is calling from different threads and clearResult() is calling from a different thread, then what will happen? Is this functions are thread safe? will getResult() return right value?
One more thing, in mid while if i call clearResult() and thread which continiuos checking getResult(), will it get right value??
if not then what should i do??
All three methods operate on ArrayList which is not a thread-safe structure. Hence, your methods are not thread-safe too. From the JavaDoc:
Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally.
Change the following line this way and you should be fine:
private static List<String> result = Collections.synchronizedList(new ArrayList<String>());
First of all ArrayList is not thread-safe, it should not be directly used in multi-threaded way without any synchronization as it may fail unexpectedly.
You can use Collections.synchronizedList(arrayList); and depend on that for thread safety.
But on a static arraylist with locks there can be a lot of contention, so you may even use CopyOnWriteArrayList if you are traversing more often than mutating the list.
Usage of Collections.synchronizedList()
private static List<String> result = Collections.synchronizedList(new ArrayList<String>());
References:
Correct way to synchronize ArrayList
Why manual synchronization while iterating Collections.synchronizedList()
You could syncronize your List with a guard object:
private static List<String> result = new ArrayList<String>();
private static Object guard = new Object();
public static void setResult(String result) {
syncronized (guard) {
result.add(result);
}
}
public static List<String> getResult() {
syncronized (guard) {
return result;
}
}
public static void clearResult() {
syncronized (guard) {
result.clear();
}
}
Let's say I have the following class that will be read heavily, but only written to occasionally. It will be used in a multi-threaded web app, so it needs to be thread safe:
public class Foo {
private volatile String foo;
public String getFoo() {
return foo;
}
public synchronized String setFoo(String in) {
this.foo = in;
}
}
Java Concurrency (http://www.ibm.com/developerworks/java/library/j-jtp06197/index.html) states that this is a fragile way to protect write access while improving read access. What is a stronger alternative to this pattern? Or any alternative if foo will need to mutable in a read-heavy environment? Thank you.
Volatile provides fast thread-safe lock-free access to a field without synchronization
private volatile String foo;
public String getFoo() {
return foo;
}
public void setFoo(String in) {
this.foo = in;
}
volatile solves 3 problems 1) memory visibility 2) atomic writes for double and long fields 3) forbids instructions reordering. But it's not enough if you need several operations over a field as one atomic transaction, such as increment. This code is broken
private volatile int id;
public void incrementId() {
id++;
}
because if 2 threads simulataneously read and increment it and save the result then the result of the first increment will be overwritten with the result of the second increment. To prevent this from happening we need to use synchronization
private int id;
public synchronized int nextId() {
return ++id;
}
or java.util.concurrent.atomic package
private AtomicInteger id = new AtomicInteger();
public void incrementId() {
return id.incrementAndGet();
}
If all you are doing is setting foo, then you don't need to synchronize the method. making the reference volatile is sufficient.
At the link you said there is this code for "infrequent updates" usage:
#ThreadSafe
public class CheesyCounter {
// Employs the cheap read-write lock trick
// All mutative operations MUST be done with the 'this' lock held
#GuardedBy("this") private volatile int value;
public int getValue() { return value; }
public synchronized int increment() {
return value++;
}
}
The increment method is only using synchronized because it is doing more than just setting the value of value as stated in the description, if all you are doing is this.foo = in; that is atomic.
In the text the "fragility of this pattern" means things can get messy very fast when you mix volatile and other synchronization methods to do more than just simple examples.
See package java.util.concurrent.locks for the interfaces Condition and Lock and the class ReentrantLock. I think that, and using synchronized is what the author means by "stronger alternatives". You should also see Object.wait, Object.notify and Object.notifyAll if you don't know that yet.
First, I had the following (here simplifed) class:
public class MyClass {
private static Map<String, Object> objects = new HashMap<String, Object>();
public static Object get(String key) {
return objects.get(key);
}
public static void set(String key, Object object) {
objects.put(key, object);
}
}
Then, I wanted to make it treahsafe, so I tried the synchronized keyword as follow:
public class MyClass {
private static Map<String, Object> objects = new HashMap<String, Object>();
public static synchronized Object get(String key) {
return objects.get(key);
}
public static synchronized void set(String key, Object object) {
objects.put(key, object);
}
}
The question is, is the synchronized keyword sufficient in my case, or is it necessary to add the volatile one, i.e.:
public class MyClass {
private static volatile Map<String, Object> objects = new HashMap<String, Object>();
public static synchronized Object get(String key) {
return objects.get(key);
}
public static synchronized void set(String key, Object object) {
objects.put(key, object);
}
}
?
Making objects volatile will only have an impact if you reassign objects. In your example you don't so it won't make a difference and is unnecessary.
Note that it is good practice to enforce "non-reassignability" by making objects final.
In your case, you could simply delegate thread safety by using a thread safe map implementation (which would certainly scale better than your synchronized implementation).
volatile does not magically make your code thread safe, it's only here to prevent the JVM from doing optimizations that could not be relevant in a multithreading context (or worse, prevent your program from running as expected).
I suggest you take a look at ConcurrentHashMap instead, it could be useful in your case.
You're not changing the reference that's stored in objects, so there's no value in using the volatile keyword.
This must be a fairly common occurrence where I have a map and wish to thread-safely expose its key set:
public MyClass {
Map<String,String> map = // ...
public final Set<String> keys() {
// returns key set
}
}
Now, if my "map" is not thread-safe, this is not safe:
public final Set<String> keys() {
return map.keySet();
}
And neither is:
public final Set<String> keys() {
return Collections.unmodifiableSet(map.keySet());
}
So I need to create a copy, such as:
public final Set<String> keys() {
return new HashSet(map.keySet());
}
However, this doesn't seem safe either because that constructor traverses the elements of the parameter and add()s them. So while this copying is going on, a ConcurrentModificationException can happen.
So then:
public final Set<String> keys() {
synchronized(map) {
return new HashSet(map.keySet());
}
}
seems like the solution. Does this look right?
That solution isn't particularly helpful unless you plan to also synchronize on the map everywhere it is used. Synchronizing on it doesn't stop someone else from invoking methods on it at the same time. It only stops them from also being able to synchronize on it.
The best solution really seems to be just use ConcurrentHashMap in the first place if you know you need concurrent puts and removes while someone may be iterating. If the concurrency behavior that class offers isn't what you need, you'll probably just need to use a fully synchronized Map.
Good question. I would use Google Guava library. More specifically com.google.common.collect.ImmutableSet.copyOf(Collection<? extends E>) method. In documentation it has been said that this method is thread safe.
Another option would be to use ConcurrentHashMap. Its keySet() is thread safe so there might be no need to synchronize or take a copy.
If you are interested on thread-safe iterator with exact snapshot of elements through out the iteration process then go for the below.
public class ThreadSafeIteratorConcurrentMap
{
private ConcurrentMap<String, String> itrSafeMap = null;
public ThreadSafeIteratorConcurrentCollection() {
itrSafeMap = new ConcurrentHashMap<String, String>
}
public void synchronized put(psConference conference, String p_key)
{
itrSafeMap.putIfAbsent(p_key, conference);
}
public psConference getConference(String p_key)
{
return (itrSafeMap.get(p_key));
}
public void synchronized remove(String p_key)
{
itrSafeMap.remove(p_key);
}
public boolean containsKey(String p_key)
{
return itrSafeMap.containsKey(p_key);
}
// Get the size of the itrSafeMap.
public int size()
{
return itrSafeMap.size();
}
public Iterator<String> valueIterator()
{
return (itrSafeMap.values().iterator());
}
public Iterator<String> keyIterator()
{
return (itrSafeMap.keySet().iterator());
}
}
Then where ever you want thread safe iterator with exact snapshot of elements; then use it in synchronized block like below.
synchronized(threadSafeIteratorConcurrentMapObject) {
Iterator<String> keyItr = threadSafeIteratorConcurrentMapObject.keyIterator();
while(keyItr.hasNext()){
// Do whatever
}
}
If you don't mind modification on the collection while iteration; only concentrating on snapshot of elements at the time of iterator creation; then without synchronization block you can use keyItr. Which is already thread safe; it wont through ConcurrentModificationException.
You can create an temporary Map using Collections.UnmodifiableMap, then iterate the keyset .