Java PriorityQueue Wait - java

I am trying to solve the readers-writers problem with writer preference in Java using multi-threading. The following is a stripped down version of what my code does. Will it work?
public PriorityQueue<myClass> pq;
public void foo(){
myClass obj = new myClass();
pq.add(obj);
obj.wait();
//Actual code
}
public void bar(){
pq.remove().notify();
}
Assume that the priority queue pq is empty initially and the constructor of the enclosing class calls the constructor of pq. Also, foo is called first and then bar. So when foo is called, it adds obj to the queue and that becomes the front element so that when the remove is called in bar that is the element that is removed. My question is, will "Actual code" be executed? Or am I performing wait() and notify() on two completely different objects? If so, how can I fix it?

You should note that PriorityQueue is not thread safe... i.e. if foo and/or bar is called concurrently they may irreparably break pq's internal state.

I'm still trying to parse your question, and so far what I can extract is that you want to implement a priority queue for myClass that exhibits writer preference. Java's off-the-shelf locks don't offer strict writer preference, but if you are OK (and it's probably best) with approximate writer preference, you can use a normal ReentrantReadWriteLock in fair mode.
Having written all this (and thought about the many ways it could go wrong) I really wonder why the java.util.concurrent implementation of PriorityBlockingQueue doesn't meet your need.
The following code is far from tested, but passes my 1:00AM sniff test.
private final PriorityQueue<myClass> pq = ...;
// associated RW lock, in fair mode (==true)
private final ReadWriteLock pqLock = new ReentrantReadWriteLock(true);
private final Condition pqWriteCondition = pqLock.writeLock().newCondition();
public void produceNew()
{
myClass obj = new myClass();
pqLock.writeLock.lock();
try {
pq.offer(obj);
pqWriteCondition.notifyAll();
} finally {
pqLock.writeLock.unlock();
}
//Actual code
}
public void consumeFirst() {
myClass consume = null;
pqLock.readLock.lock();
try {
consume = pq.poll();
while (consume == null) {
pqWriteCondition.wait();
consume = pq.poll();
}
} finally {
pqLock.readLock.unlock();
}
//Actual code
}

Related

Java Concurrency volatile for reading synchronization for writing

I need to create a class that has a shared-between-threads Object (lets call is SharedObject). The special thing about SharedObject is that it holds a String that will be returned in multithreaded environment, and sometimes the entire SharedObject will be written to by changing field reference to newly created object.
I do not want to make the read and write both synchronised on the same monitor because the write scenario is happening rarely while read scenario is quite common. Therefore I did the following:
public class ObjectHolder {
private volatile SharedObject sharedObject;
public String getSharedObjectString() {
if (!isObjectStillValid()) {
obtainNewSharedObject()
}
return sharedObject.getCommonString()
}
public synchronized void obtainNewSharedObject() {
/* This is in case multiple threads wait on this lock,
after first one obtains new object the others can just
use it and should not obtain a new one */
if(!isObjectStillValid()) {
sharedObject = new SharedObject(/*some parameters from somewhere*/)
}
}
}
From what I have read from documentation and on stackoverflow, the synchronized keyword will assure only one thread can access the synchronised block on the same object instance(therefore write race/multiple unnecessary writes is a non-issue) while volatile keyword on the field reference will assure the reference value is written directly to the main program memory (not cached locally).
Are there any other pitfalls I am missing?
I want to be sure that within synchronized block when sharedObject is written to, the new value of sharedObject is present for any other thread at latest when lock for obtainNewSharedObject() is released. Should this not be guaranteed, I could encounter scenarios of unnecessary writes and replacing correct values which are a big problem for this case.
I know to be absolutely safe I could just make getSharedObjectString() synchronized by itself however as stated previously I do not want to block reading if not needed.
This way reading is non-blocking, when a write scenario occurs it is blocking.
I should probably mention method isObjectStillValid() is thread independant (entirely SharedObject and System clock based) therefore a valid Thread-free check to be used for write scenarios.
Edit: Please note I could not find a similar topic on stackoverflow, but it may exist. Sorry if that is the case.
Edit2: Thank you for all the comments. Edit because apparently I cannot upvote yet (I can, but it does not show). While my solution is functional as long as isObjectStillValid is thread-safe, it can suffer from decreased performance due to multiple accesses to volatile field. I will improve it most likely using the upgraded double-checked locking solution. I will also in-depth analyse all the other possibilities mentioned here.
Why don't you use AtomicReference. It uses optimistic locking, meaning that no actual thread locking is involved. Internally it uses Compare and Swap. If you look at the implementation it uses volatile in its implementation and I would trust Doug Lea to implement it correctly :)
Apart from this, there many more ways for synchronization between lot of readers and some writers - ReadWriteLock
This looks like a classic double-checked locking pattern. While your implementation is logically correct - thanks to the use of volatile on sharedObject - it might not be the most performant.
The recommended pattern for Java 1.5 on is shown on the Wikipedia page linked.
// Works with acquire/release semantics for volatile in Java 1.5 and later
// Broken under Java 1.4 and earlier semantics for volatile
class Foo {
private volatile Helper helper;
public Helper getHelper() {
Helper localRef = helper;
if (localRef == null) {
synchronized(this) {
localRef = helper;
if (localRef == null) {
helper = localRef = new Helper();
}
}
}
return localRef;
}
// other functions and members...
}
Note the use of a localRef for accessing the helper field. This limits access to the volatile field in the simple case to a single read instead of potentially twice; once for the check and once for the return. See the Wikipedia page again, just after the recommended pattern sample.
Note the local variable "localRef", which seems unnecessary. The effect of this is that in cases where helper is already initialized (i.e., most of the time), the volatile field is only accessed once (due to "return localRef;" instead of "return helper;"), which can improve the method's overall performance by as much as 25 percent.[7]
Depending on how isObjectStillValid() accesses sharedObject, you might benefit from a similar pattern.
This sounds like the use of a ReadWriteLock would be appropiate.
The basic idea is that there can be multiple readers simultaniously or one writer exclusively. Here can you find an Example how to use it in a List implementation.
Copy paste in case the side goes down:
import java.util.*;
import java.util.concurrent.locks.*;
/**
* ReadWriteList.java
* This class demonstrates how to use ReadWriteLock to add concurrency
* features to a non-threadsafe collection
* #author www.codejava.net
*/
public class ReadWriteList<E> {
private List<E> list = new ArrayList<>();
private ReadWriteLock rwLock = new ReentrantReadWriteLock();
public ReadWriteList(E... initialElements) {
list.addAll(Arrays.asList(initialElements));
}
public void add(E element) {
Lock writeLock = rwLock.writeLock();
writeLock.lock();
try {
list.add(element);
} finally {
writeLock.unlock();
}
}
public E get(int index) {
Lock readLock = rwLock.readLock();
readLock.lock();
try {
return list.get(index);
} finally {
readLock.unlock();
}
}
public int size() {
Lock readLock = rwLock.readLock();
readLock.lock();
try {
return list.size();
} finally {
readLock.unlock();
}
}
}

Java synchronizing based on a parameter (named mutex/lock)

I'm looking for a way to synchronize a method based on the parameter it receives, something like this:
public synchronized void doSomething(name){
//some code
}
I want the method doSomething to be synchronized based on the name parameter like this:
Thread 1: doSomething("a");
Thread 2: doSomething("b");
Thread 3: doSomething("c");
Thread 4: doSomething("a");
Thread 1 , Thread 2 and Thread 3 will execute the code without being synchronized , but Thread 4 will wait until Thread 1 has finished the code because it has the same "a" value.
Thanks
UPDATE
Based on Tudor explanation I think I'm facing another problem:
here is a sample of the new code:
private HashMap locks=new HashMap();
public void doSomething(String name){
locks.put(name,new Object());
synchronized(locks.get(name)) {
// ...
}
locks.remove(name);
}
The reason why I don't populate the locks map is because name can have any value.
Based on the sample above , the problem can appear when adding / deleting values from the hashmap by multiple threads in the same time, since HashMap is not thread-safe.
So my question is if I make the HashMap a ConcurrentHashMap which is thread safe, will the synchronized block stop other threads from accessing locks.get(name) ??
TL;DR:
I use ConcurrentReferenceHashMap from the Spring Framework. Please check the code below.
Although this thread is old, it is still interesting. Therefore, I would like to share my approach with Spring Framework.
What we are trying to implement is called named mutex/lock. As suggested by Tudor's answer, the idea is to have a Map to store the lock name and the lock object. The code will look like below (I copy it from his answer):
Map<String, Object> locks = new HashMap<String, Object>();
locks.put("a", new Object());
locks.put("b", new Object());
However, this approach has 2 drawbacks:
The OP already pointed out the first one: how to synchronize the access to the locks hash map?
How to remove some locks which are not necessary anymore? Otherwise, the locks hash map will keep growing.
The first problem can be solved by using ConcurrentHashMap. For the second problem, we have 2 options: manually check and remove locks from the map, or somehow let the garbage collector knows which locks are no longer used and the GC will remove them. I will go with the second way.
When we use HashMap, or ConcurrentHashMap, it creates strong references. To implement the solution discussed above, weak references should be used instead (to understand what is a strong/weak reference, please refer to this article or this post).
So, I use ConcurrentReferenceHashMap from the Spring Framework. As described in the documentation:
A ConcurrentHashMap that uses soft or weak references for both keys
and values.
This class can be used as an alternative to
Collections.synchronizedMap(new WeakHashMap<K, Reference<V>>()) in
order to support better performance when accessed concurrently. This
implementation follows the same design constraints as
ConcurrentHashMap with the exception that null values and null keys
are supported.
Here is my code. The MutexFactory manages all the locks with <K> is the type of the key.
#Component
public class MutexFactory<K> {
private ConcurrentReferenceHashMap<K, Object> map;
public MutexFactory() {
this.map = new ConcurrentReferenceHashMap<>();
}
public Object getMutex(K key) {
return this.map.compute(key, (k, v) -> v == null ? new Object() : v);
}
}
Usage:
#Autowired
private MutexFactory<String> mutexFactory;
public void doSomething(String name){
synchronized(mutexFactory.getMutex(name)) {
// ...
}
}
Unit test (this test uses the awaitility library for some methods, e.g. await(), atMost(), until()):
public class MutexFactoryTests {
private final int THREAD_COUNT = 16;
#Test
public void singleKeyTest() {
MutexFactory<String> mutexFactory = new MutexFactory<>();
String id = UUID.randomUUID().toString();
final int[] count = {0};
IntStream.range(0, THREAD_COUNT)
.parallel()
.forEach(i -> {
synchronized (mutexFactory.getMutex(id)) {
count[0]++;
}
});
await().atMost(5, TimeUnit.SECONDS)
.until(() -> count[0] == THREAD_COUNT);
Assert.assertEquals(count[0], THREAD_COUNT);
}
}
Use a map to associate strings with lock objects:
Map<String, Object> locks = new HashMap<String, Object>();
locks.put("a", new Object());
locks.put("b", new Object());
// etc.
then:
public void doSomething(String name){
synchronized(locks.get(name)) {
// ...
}
}
The answer of Tudor is fine, but it's static and not scalable. My solution is dynamic and scalable, but it goes with increased complexity in the implementation. The outside world can use this class just like using a Lock, as this class implements the interface. You get an instance of a parameterized lock by the factory method getCanonicalParameterLock.
package lock;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public final class ParameterLock implements Lock {
/** Holds a WeakKeyLockPair for each parameter. The mapping may be deleted upon garbage collection
* if the canonical key is not strongly referenced anymore (by the threads using the Lock). */
private static final Map<Object, WeakKeyLockPair> locks = new WeakHashMap<>();
private final Object key;
private final Lock lock;
private ParameterLock (Object key, Lock lock) {
this.key = key;
this.lock = lock;
}
private static final class WeakKeyLockPair {
/** The weakly-referenced parameter. If it were strongly referenced, the entries of
* the lock Map would never be garbage collected, causing a memory leak. */
private final Reference<Object> param;
/** The actual lock object on which threads will synchronize. */
private final Lock lock;
private WeakKeyLockPair (Object param, Lock lock) {
this.param = new WeakReference<>(param);
this.lock = lock;
}
}
public static Lock getCanonicalParameterLock (Object param) {
Object canonical = null;
Lock lock = null;
synchronized (locks) {
WeakKeyLockPair pair = locks.get(param);
if (pair != null) {
canonical = pair.param.get(); // could return null!
}
if (canonical == null) { // no such entry or the reference was cleared in the meantime
canonical = param; // the first thread (the current thread) delivers the new canonical key
pair = new WeakKeyLockPair(canonical, new ReentrantLock());
locks.put(canonical, pair);
}
}
// the canonical key is strongly referenced now...
lock = locks.get(canonical).lock; // ...so this is guaranteed not to return null
// ... but the key must be kept strongly referenced after this method returns,
// so wrap it in the Lock implementation, which a thread of course needs
// to be able to synchronize. This enforces a thread to have a strong reference
// to the key, while it isn't aware of it (as this method declares to return a
// Lock rather than a ParameterLock).
return new ParameterLock(canonical, lock);
}
#Override
public void lock() {
lock.lock();
}
#Override
public void lockInterruptibly() throws InterruptedException {
lock.lockInterruptibly();
}
#Override
public boolean tryLock() {
return lock.tryLock();
}
#Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return lock.tryLock(time, unit);
}
#Override
public void unlock() {
lock.unlock();
}
#Override
public Condition newCondition() {
return lock.newCondition();
}
}
Of course you'd need a canonical key for a given parameter, otherwise threads would not be synchronized as they would be using a different Lock. Canonicalization is the equivalent of the internalization of Strings in Tudor's solution. Where String.intern() is itself thread-safe, my 'canonical pool' is not, so I need extra synchronization on the WeakHashMap.
This solution works for any type of Object. However, make sure to implement equals and hashCode correctly in custom classes, because if not, threading issues will arise as multiple threads could be using different Lock objects to synchronize on!
The choice for a WeakHashMap is explained by the ease of memory management it brings. How else could one know that no thread is using a particular Lock anymore? And if this could be known, how could you safely delete the entry out of the Map? You would need to synchronize upon deletion, because you have a race condition between an arriving thread wanting to use the Lock, and the action of deleting the Lock from the Map. All these things are just solved by using weak references, so the VM does the work for you, and this simplifies the implementation a lot. If you inspected the API of WeakReference, you would find that relying on weak references is thread-safe.
Now inspect this test program (you need to run it from inside the ParameterLock class, due to private visibility of some fields):
public static void main(String[] args) {
Runnable run1 = new Runnable() {
#Override
public void run() {
sync(new Integer(5));
System.gc();
}
};
Runnable run2 = new Runnable() {
#Override
public void run() {
sync(new Integer(5));
System.gc();
}
};
Thread t1 = new Thread(run1);
Thread t2 = new Thread(run2);
t1.start();
t2.start();
try {
t1.join();
t2.join();
while (locks.size() != 0) {
System.gc();
System.out.println(locks);
}
System.out.println("FINISHED!");
} catch (InterruptedException ex) {
// those threads won't be interrupted
}
}
private static void sync (Object param) {
Lock lock = ParameterLock.getCanonicalParameterLock(param);
lock.lock();
try {
System.out.println("Thread="+Thread.currentThread().getName()+", lock=" + ((ParameterLock) lock).lock);
// do some work while having the lock
} finally {
lock.unlock();
}
}
Chances are very high that you would see that both threads are using the same lock object, and so they are synchronized. Example output:
Thread=Thread-0, lock=java.util.concurrent.locks.ReentrantLock#8965fb[Locked by thread Thread-0]
Thread=Thread-1, lock=java.util.concurrent.locks.ReentrantLock#8965fb[Locked by thread Thread-1]
FINISHED!
However, with some chance it might be that the 2 threads do not overlap in execution, and therefore it is not required that they use the same lock. You could easily enforce this behavior in debugging mode by setting breakpoints at the right locations, forcing the first or second thread to stop wherever necessary. You will also notice that after the Garbage Collection on the main thread, the WeakHashMap will be cleared, which is of course correct, as the main thread waited for both worker threads to finish their job by calling Thread.join() before calling the garbage collector. This indeed means that no strong reference to the (Parameter)Lock can exist anymore inside a worker thread, so the reference can be cleared from the weak hashmap. If another thread now wants to synchronize on the same parameter, a new Lock will be created in the synchronized part in getCanonicalParameterLock.
Now repeat the test with any pair that has the same canonical representation (= they are equal, so a.equals(b)), and see that it still works:
sync("a");
sync(new String("a"))
sync(new Boolean(true));
sync(new Boolean(true));
etc.
Basically, this class offers you the following functionality:
Parameterized synchronization
Encapsulated memory management
The ability to work with any type of object (under the condition that equals and hashCode is implemented properly)
Implements the Lock interface
This Lock implementation has been tested by modifying an ArrayList concurrently with 10 threads iterating 1000 times, doing this: adding 2 items, then deleting the last found list entry by iterating the full list. A lock is requested per iteration, so in total 10*1000 locks will be requested. No ConcurrentModificationException was thrown, and after all worker threads have finished the total amount of items was 10*1000. On every single modification, a lock was requested by calling ParameterLock.getCanonicalParameterLock(new String("a")), so a new parameter object is used to test the correctness of the canonicalization.
Please note that you shouldn't be using String literals and primitive types for parameters. As String literals are automatically interned, they always have a strong reference, and so if the first thread arrives with a String literal for its parameter then the lock pool will never be freed from the entry, which is a memory leak. The same story goes for autoboxing primitives: e.g. Integer has a caching mechanism that will reuse existing Integer objects during the process of autoboxing, also causing a strong reference to exist. Addressing this, however, this is a different story.
Check out this framework. Seems you're looking for something like this.
public class WeatherServiceProxy {
...
private final KeyLockManager lockManager = KeyLockManagers.newManager();
public void updateWeatherData(String cityName, Date samplingTime, float temperature) {
lockManager.executeLocked(cityName, new LockCallback() {
public void doInLock() {
delegate.updateWeatherData(cityName, samplingTime, temperature);
}
});
}
https://code.google.com/p/jkeylockmanager/
I've created a tokenProvider based on the IdMutexProvider of McDowell.
The manager uses a WeakHashMap which takes care of cleaning up unused locks.
You could find my implementation here.
I've found a proper answer through another stackoverflow question: How to acquire a lock by a key
I copied the answer here:
Guava has something like this being released in 13.0; you can get it out of HEAD if you like.
Striped more or less allocates a specific number of locks, and then assigns strings to locks based on their hash code. The API looks more or less like
Striped<Lock> locks = Striped.lock(stripes);
Lock l = locks.get(string);
l.lock();
try {
// do stuff
} finally {
l.unlock();
}
More or less, the controllable number of stripes lets you trade concurrency against memory usage, because allocating a full lock for each string key can get expensive; essentially, you only get lock contention when you get hash collisions, which are (predictably) rare.
Just extending on to Triet Doan's answer, we also need to take care of if the MutexFactory can be used at multiple places, as with currently suggested code we will end up with same MutexFactory at all places of its usage.
For example:-
#Autowired
MutexFactory<CustomObject1> mutexFactory1;
#Autowired
MutexFactory<CustomObject2> mutexFactory2;
Both mutexFactory1 & mutexFactory2 will refer to the same instance of factory even if their type differs, this is due to the fact that a single instance of MutexFactory is created by spring during application startup and same is used for both mutexFactory1 & mutexFactory2.
So here is the extra Scope annotation that needs to be put in to avoid above case-
#Component
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class MutexFactory<K> {
private ConcurrentReferenceHashMap<K, Object> map;
public MutexFactory() {
this.map = new ConcurrentReferenceHashMap<>();
}
public Object getMutex(K key) {
return this.map.compute(key, (k, v) -> v == null ? new Object() : v);
}
}
I've used a cache to store lock objects. The my cache will expire objects after a period, which really only needs to be longer that the time it takes the synchronized process to run
`
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
...
private final Cache<String, Object> mediapackageLockCache = CacheBuilder.newBuilder().expireAfterWrite(DEFAULT_CACHE_EXPIRE, TimeUnit.SECONDS).build();
...
public void doSomething(foo) {
Object lock = mediapackageLockCache.getIfPresent(foo.toSting());
if (lock == null) {
lock = new Object();
mediapackageLockCache.put(foo.toString(), lock);
}
synchronized(lock) {
// execute code on foo
...
}
}
`
I have a much simpler, scalable implementation akin to #timmons post taking advantage of guavas LoadingCache with weakValues. You will want to read the help files on "equality" to understand the suggestion I have made.
Define the following weakValued cache.
private final LoadingCache<String,String> syncStrings = CacheBuilder.newBuilder().weakValues().build(new CacheLoader<String, String>() {
public String load(String x) throws ExecutionException {
return new String(x);
}
});
public void doSomething(String x) {
x = syncStrings.get(x);
synchronized(x) {
..... // whatever it is you want to do
}
}
Now! As a result of the JVM, we do not have to worry that the cache is growing too large, it only holds the cached strings as long as necessary and the garbage manager/guava does the heavy lifting.

How to correctly create a SynchronizedStack class?

I made a simple synchronized Stack object in Java, just for training purposes.
Here is what I did:
public class SynchronizedStack {
private ArrayDeque<Integer> stack;
public SynchronizedStack(){
this.stack = new ArrayDeque<Integer>();
}
public synchronized Integer pop(){
return this.stack.pop();
}
public synchronized int forcePop(){
while(isEmpty()){
System.out.println(" Stack is empty");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return this.stack.pop();
}
public synchronized void push(int i){
this.stack.push(i);
notifyAll();
}
public boolean isEmpty(){
return this.stack.isEmpty();
}
public synchronized void pushAll(int[] d){
for(int i = 0; i < d.length; i++){
this.stack.push(i);
}
notifyAll();
}
public synchronized String toString(){
String s = "[";
Iterator<Integer> it = this.stack.iterator();
while(it.hasNext()){
s += it.next() + ", ";
}
s += "]";
return s;
}
}
Here are my questions:
Is it OK not to synchronize the isEmtpy() method? I figured it was because even if another Thread is modifying the stack at the same time, it would still return a coherent result (there is no operation that goes into a isEmpty state that is neither initial or final). Or is it a better design to have all the methods of a synchronized object synchronized?
I don't like the forcePop() method. I just wanted to create a thread that was able to wait until an item was pushed into the stack before poping an element, and I thought the best option was to do the loop with the wait() in the run() method of the thread, but I can't because it throws an IllegalMonitorStatException. What is the proper method to do something like this?
Any other comment/suggestion?
Thank you!
Stack itself is already synchronized, so it doesn't make sense to apply synchronization again (use ArrayDeque if you want a non-synchronized stack implementation)
It's NOT OK (aside from the fact from the previous point), because lack of synchronization may cause memory visibility effects.
forcePop() is pretty good. Though it should pass InterruptedException without catching it to follow the contract of interruptable blocking method. It would allow you to interrupt a thread blocked at forcePop() call by calling Thread.interrupt().
Assuming that stack.isEmpty() won't need synchronization might be true, but you are relying on an implementation detail of a class that you have no control over.
The javadocs of Stack state that the class is not thread-safe, so you should synchronize all access.
I think you're mixing idioms a little. You are backing your SynchronizedStack with java.util.Stack, which in turn is backed by java.util.Vector, which is synchronized. I think you should encapsulate the wait() and notify() behaivor in another class.
The only problem with not synchronizing isEmpty() is that you don't know what's happening underneath. While your reasoning is, well, reasonable, it assumes that the underlying Stack is also behaving in a reasonable manner. Which it probably is in this case, but you can't rely on it in general.
And the second part of your question, there's nothing wrong with a blocking pop operation, see this for a complete implementation of all the possible strategies.
And one other suggestion: if you're creating a class that is likely to be re-used in several parts of an application (or even several applications), don't use synchronized methods. Do this instead:
public class Whatever {
private Object lock = new Object();
public void doSomething() {
synchronized( lock ) {
...
}
}
}
The reason for this is that you don't really know if users of your class want to synchronize on your Whatever instances or not. If they do, they might interfere with the operation of the class itself. This way you've got your very own private lock which nobody can interfere with.

Waiting on objects after putting them into priority queue in Java

I am trying to solve the readers-writers problem with writer preference in Java using multi-threading. The following is a stripped down version of what my code does. Will it work?
public PriorityBlockingQueue<myClass> pq;
public void foo(){
myClass obj = new myClass();
pq.add(obj);
obj.wait();
//Actual code
}
public void bar(){
pq.remove().notify();
}
Assume that the priority queue pq is empty initially and the constructor of the enclosing class calls the constructor of pq. Also, foo is called first by one thread and then bar by another thread. So when foo is called, it adds obj to the queue and that becomes the front element so that when the remove is called in bar that is the element that is removed. My question is, will "Actual code" be executed? Or am I performing wait() and notify() on two completely different objects? If so, how can I fix it?
The main issue I can see with this is that threads can wake up spuriously... so you should always have some data associated with conditions. Also notifyAll() is less likely to result in deadlock... so:
public void foo() {
MyClass obj = new MyClass();
pq.add(obj);
synchronized(obj) {
while (!obj.isDoneBeingProcessed()) {
obj.wait();
}
}
}
public void bar() {
MyClass next = pq.remove();
if (!next) {
return;
}
next.doProcessing();
synchronized(next) {
next.setDone(true);
next.notifyAll();
}
}
Note, though, that this code really doesn't make sense because it essentially serializes the entire computation. It would make more sense if you were to enqueue everything in one thread, while in another thread you did the processing, and then ... only at the end or in another thread attempted to wait on everything. Putting the wait in the producer phase before everything has been produced effectively serializes your entire computation.

How do I create a thread-safe write-once read-many value in Java?

This is a problem I encounter frequently in working with more complex systems and which I have never figured out a good way to solve. It usually involves variations on the theme of a shared object whose construction and initialization are necessarily two distinct steps. This is generally because of architectural requirements, similar to applets, so answers that suggest I consolidate construction and initialization are not useful. The systems have to target Java 4 at the latest, so answers that suggest support available only in later JVMs are not useful either.
By way of example, let's say I have a class that is structured to fit into an application framework like so:
public class MyClass
{
private /*ideally-final*/ SomeObject someObject;
MyClass() {
someObject=null;
}
public void startup() {
someObject=new SomeObject(...arguments from environment which are not available until startup is called...);
}
public void shutdown() {
someObject=null; // this is not necessary, I am just expressing the intended scope of someObject explicitly
}
}
I can't make someObject final since it can't be set until startup() is invoked. But I would really like it to reflect its write-once semantics and be able to directly access it from multiple threads, preferably avoiding synchronization.
The idea being to express and enforce a degree of finalness, I conjecture that I could create a generic container, like so (UPDATE - corrected threading sematics of this class):
public class WormRef<T>
{
private volatile T reference; // wrapped reference
public WormRef() {
reference=null;
}
public WormRef<T> init(T val) {
if(reference!=null) { throw new IllegalStateException("The WormRef container is already initialized"); }
reference=val;
return this;
}
public T get() {
if(reference==null) { throw new IllegalStateException("The WormRef container is not initialized"); }
return reference;
}
}
and then in MyClass, above, do:
private final WormRef<SomeObject> someObject;
MyClass() {
someObject=new WormRef<SomeObject>();
}
public void startup() {
someObject.init(new SomeObject(...));
}
public void sometimeLater() {
someObject.get().doSomething();
}
Which raises some questions for me:
Is there a better way, or existing Java object (would have to be available in Java 4)?
Secondarily, in terms of thread safety:
Is this thread-safe provided that no other thread accesses someObject.get() until after its set() has been called. The other threads will only invoke methods on MyClass between startup() and shutdown() - the framework guarantees this.
Given the completely unsynchronized WormReference container, it is ever possible under either JMM to see a value of object which is neither null nor a reference to a SomeObject? In other words, does the JMM always guarantee that no thread can observe the memory of an object to be whatever values happened to be on the heap when the object was allocated. I believe the answer is "Yes" because allocation explicitly zeroes the allocated memory - but can CPU caching result in something else being observed at a given memory location?
Is it sufficient to make WormRef.reference volatile to ensure proper multithreaded semantics?
Note the primary thrust of this question is how to express and enforce the finalness of someObject without being able to actually mark it final; secondary is what is necessary for thread-safety. That is, don't get too hung up on the thread-safety aspect of this.
I would start by declaring your someObject volatile.
private volatile SomeObject someObject;
Volatile keyword creates a memory barrier, which means separate threads will always see updated memory when referencing someObject.
In your current implementation some threads may still see someObject as null even after startup has been called.
Actually this volatile technique is used a lot by collections declared in java.util.concurrent package.
And as some other posters suggest here, if all else fails fall back to full synchronization.
I would remove the setter method in WoRmObject, and provide a synchronised init() method which throws an exception if (object != null)
Consider using AtomicReference as a delegate in this object-container you're trying to create. For example:
public class Foo<Bar> {
private final AtomicReference<Bar> myBar = new AtomicReference<Bar>();
public Bar get() {
if (myBar.get()==null) myBar.compareAndSet(null,init());
return myBar.get();
}
Bar init() { /* ... */ }
//...
}
EDITED: That will set once, with some lazy-initialization method. It's not perfect for blocking multiple calls to a (presumably expensive) init(), but it could be worse. You could stick the instantiation of myBar into constructor, and then later add a constructor that allows assignment as well, if provided the correct info.
There's some general discussion of thread-safe, singleton instantiation (which is pretty similar to your problem) at, for example, this site.
In theory it would be sufficient to rewrite startup() as follows:
public synchronized void startup() {
if (someObject == null) someObject = new SomeObject();
}
By the way, although the WoRmObject is final, threads can still invoke set() multiple times. You'll really need to add some synchronization.
update: I played a bit round it and created an SSCCE, you may find it useful to play a bit around with it :)
package com.stackoverflow.q2428725;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String... args) throws Exception {
Bean bean = new Bean();
ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);
executor.schedule(new StartupTask(bean), 2, TimeUnit.SECONDS);
executor.schedule(new StartupTask(bean), 2, TimeUnit.SECONDS);
Future<String> result1 = executor.submit(new GetTask(bean));
Future<String> result2 = executor.submit(new GetTask(bean));
System.out.println("Result1: " + result1.get());
System.out.println("Result2: " + result2.get());
executor.shutdown();
}
}
class Bean {
private String property;
private CountDownLatch latch = new CountDownLatch(1);
public synchronized void startup() {
if (property == null) {
System.out.println("Setting property.");
property = "foo";
latch.countDown();
} else {
System.out.println("Property already set!");
}
}
public String get() {
try {
latch.await();
} catch (InterruptedException e) {
// handle.
}
return property;
}
}
class StartupTask implements Runnable {
private Bean bean;
public StartupTask(Bean bean) {
this.bean = bean;
}
public void run() {
System.out.println("Starting up bean...");
bean.startup();
System.out.println("Bean started!");
}
}
class GetTask implements Callable<String> {
private Bean bean;
public GetTask(Bean bean) {
this.bean = bean;
}
public String call() {
System.out.println("Getting bean property...");
String property = bean.get();
System.out.println("Bean property got!");
return property;
}
}
The CountDownLatch will cause all await() calls to block until the countdown reaches zero.
It is most likely thread safe, from your description of the framework. There must have been a memory barrier somewhere between calling myobj.startup() and making myobj available to other threads. That guarantees that the writes in startup() will be visible to other threads. Therefore you don't have to worry about thread safety because the framework does it. There is no free lunch though; everytime another thread obtains access to myobj through the framework, it must involve sync or volatile read.
If you look into the framework and list the code in the path, you'll see sync/volatile in proper places that make your code thread safe. That is, if the framework is correctly implemented.
Let's examine a typical swing example, where a worker threads does some calculation, saves the results in a global variable x, then sends a repaint event. The GUI thread upon receiving the repaint event, reads the results from the global variable x, and repaints accordingly.
Neither the worker thread nor the repaint code does any synchronization or volatile read/write on anything. There must be tens of thousands of implementations like this. Luckily they are all thread safe even though the programmers paid no special attention. Why? Because the event queue is synchronized; we have a nice happends-before chain:
write x - insert event - read event - read x
Therefore write x and read x are properly synchronized, implicitly via event framework.
how about synchronization?
No it is not thread safe. Without synchronization, the new state of your variable might never get communicated to other threads.
Yes, as far as I know references are atomic so you will see either null or the reference. Note that the state of the referenced object is a completely different story
Could you use a ThreadLocal that only allows each thread's value to be set once?
There are a LOT of wrong ways to do lazy instantiation, especially in Java.
In short, the naive approach is to create a private object, a public synchronized init method, and a public unsynchronized get method that performs a null check on your object and calls init if necessary. The intricacies of the problem come in performing the null check in a thread safe way.
This article should be of use: http://en.wikipedia.org/wiki/Double-checked_locking
This specific topic, in Java, is discussed in depth in Doug Lea's 'Concurrent Programming in Java' which is somewhat out of date, and in 'Java Concurrency in Practice' coauthored by Lea and others. In particular, CPJ was published before the release of Java 5, which significantly improved Java's concurrency controls.
I can post more specifics when I get home and have access to said books.
This is my final answer, Regis1 :
/**
* Provides a simple write-one, read-many wrapper for an object reference for those situations
* where you have an instance variable which you would like to declare as final but can't because
* the instance initialization extends beyond construction.
* <p>
* An example would be <code>java.awt.Applet</code> with its constructor, <code>init()</code> and
* <code>start()</code> methods.
* <p>
* Threading Design : [ ] Single Threaded [x] Threadsafe [ ] Immutable [ ] Isolated
*
* #since Build 2010.0311.1923
*/
public class WormRef<T>
extends Object
{
private volatile T reference; // wrapped reference
public WormRef() {
super();
reference=null;
}
public WormRef<T> init(T val) {
// Use synchronization to prevent a race-condition whereby the following interation could happen between three threads
//
// Thread 1 Thread 2 Thread 3
// --------------- --------------- ---------------
// init-read null
// init-read null
// init-write A
// get A
// init-write B
// get B
//
// whereby Thread 3 sees A on the first get and B on subsequent gets.
synchronized(this) {
if(reference!=null) { throw new IllegalStateException("The WormRef container is already initialized"); }
reference=val;
}
return this;
}
public T get() {
if(reference==null) { throw new IllegalStateException("The WormRef container is not initialized"); }
return reference;
}
} // END PUBLIC CLASS
(1) Confer the game show "So you want to be a millionaire", hosted by Regis Philburn.
Just my little version based on AtomicReference. It's probably not the best, but I believe it to be clean and easy to use:
public static class ImmutableReference<V> {
private AtomicReference<V> ref = new AtomicReference<V>(null);
public boolean trySet(V v)
{
if(v == null)
throw new IllegalArgumentException("ImmutableReference cannot hold null values");
return ref.compareAndSet(null, v);
}
public void set(V v)
{
if(!trySet(v)) throw new IllegalStateException("Trying to modify an immutable reference");
}
public V get()
{
V v = ref.get();
if(v == null)
throw new IllegalStateException("Not initialized immutable reference.");
return v;
}
public V tryGet()
{
return ref.get();
}
}
First question: Why can't you just make start up a private method, called in the constructor, then it can be final. This would ensure thread safety after the constructor is called, as it is invisible before and only read after the constructor returns. Or re-factor your class structure so that the start-up method can create the MyClass object as part of its constructor. In may ways this particular case seems like a case of poor structure, where you really just want to make it final and immutable.
The easy Approach, if the class is immutable, and is read only after it is created, then wrap it in an Immutable List from guava. You can also make your own immutable wrapper which defensively copies when asked to return the reference, so this prevents a client from changing the reference. If it is immutable internally, then no further synchronization is needed, and unsynchronized reads are permissible. You can set your wrapper to defensively copy on request, so even attempts to write to it fail cleanly (they just don't do anything). You may need a memory barrier, or you may be able to do lazy initialisation, although note that lazy initialisation may require further synchronization, as you may get several unsynchronized read requests while the object is being constructed.
The slightly more involved approach would involve using an enumeration. Since enumerations are guaranteed singleton, then as soon as the enumeration is created it is fixed for ever. You still have to make sure that the object is internally immutable, but it does guarantee its singleton status. Without much effort.
The following class could answer your question. Some thread-safety achieved by using a volatile intermediate variable in conjunction with final value keeper in the provided generic. You may consider further increase of it by using synchronized setter/getter. Hope it helps.
https://stackoverflow.com/a/38290652/6519864

Categories

Resources