Waiting on objects after putting them into priority queue in Java - 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.

Related

Why is it "dangerous" to synchronize on method parameter

My IDE (JetBrains IntelliJ IDEA) warns me about synchronizing on a method parameter even when it's always an object.
The full warning reads:
Synchronization on method parameter 's' ... Inspection
info: Reports synchronization on a local variable or parameter. It is
very difficult to guarantee correctness when such synchronization is
used. It may be possible to improve code like this by controlling
access through e.g. a synchronized wrapper class, or by synchronizing
on a field.
My guess is that with auto-boxing, the parameter might be a primitive which gets converted to an object? Although, with auto-boxing, I would assume it's always an object, but maybe not a shared object which means it wouldn't be shared synchronization.
Anyone know why the warning would be present? In my case ShortCircuit type is always an object and the IDE should be able to know that.
The thing is that if you forget to synchronize on ShortCircuit when using it in other places of your code you might get unpredictable results. It's a lot better to synchronize inside the ShortCircuit class so it's guaranteed to be thread safe.
Update
If you're moving the synchronization outside of the class it's inherently unsafe for threading. If you want to synchronize on it externally you will have to audit all places it's used, that's why you get the warning. It's all about good encapsulation. It will be even worse if it is in a public API.
Now if you move the fireFinalCallback method to your ShortCircuit class you can guarantee that the callback won't fire simultaneously. Otherwise you need to have this in mind when calling the methods on that class.
As jontro already mentioned in his answer (and basically, as the warning already says) : This sort of synchronization on the ShortCircuit object does not have the effect that the developer probably hoped to achieve. Unfortunately, the tooltip in your screenshot hides the actual code, but it seems like the code could roughly be
synchronized (s)
{
if (!s.isFinalCallbackFired())
{
s.doFire();
}
}
That is: It is first checked whether isFinalCallbackFired returns false, and if this is the case, something (hidden) is done, which likely causes the isFinalCallbackFired state to switch to true.
So my assumption is, roughly, that the goal of putting the if statement into the synchronized block was to make sure that doFire is always called exactly once.
And indeed, at this point, the synchronization could be justified. More specifically, and a bit oversimplified:
What can be guaranteed:
When two threads are executing the fireFinalCallback method with the same ShortCircuit parameter, the synchronized block will guarantee that only one thread at a time can check the isFinalCallbackFired state and (if it is false) call the doFire method. So it is guaranteed that doFire will be called only once.
What can not be guaranteed:
When one thread is executing the fireFinalCallback method, and another thread does any operation on the ShortCircuit object (like calling doFire), then this might lead to an inconsistent state. Particularly, if another thread also does
if (!s.isFinalCallbackFired())
{
s.doFire();
}
but without synchronizing on the object, then doFire may be called twice.
The following is an MCVE that illustrates the effect:
public class SynchronizeOnParameter
{
public static void main(String[] args)
{
System.out.println("Running test without synchronization:");
runWithoutSync();
System.out.println();
System.out.println("Running test with synchronization:");
runWithSync();
System.out.println();
System.out.println("Running test with wrong synchronization:");
runWithSyncWrong();
System.out.println();
}
private static void runWithoutSync()
{
ShortCircuit s = new ShortCircuit();
new Thread(() -> fireFinalCallbackWithoutSync(s)).start();
pause(250);
new Thread(() -> fireFinalCallbackWithoutSync(s)).start();
pause(1000);
}
private static void runWithSync()
{
ShortCircuit s = new ShortCircuit();
new Thread(() -> fireFinalCallbackWithSync(s)).start();
pause(250);
new Thread(() -> fireFinalCallbackWithSync(s)).start();
pause(1000);
}
private static void runWithSyncWrong()
{
ShortCircuit s = new ShortCircuit();
new Thread(() -> fireFinalCallbackWithSync(s)).start();
if (!s.isFinalCallbackFired())
{
s.doFire();
}
}
private static void fireFinalCallbackWithoutSync(ShortCircuit s)
{
if (!s.isFinalCallbackFired())
{
s.doFire();
}
}
private static void fireFinalCallbackWithSync(ShortCircuit s)
{
synchronized (s)
{
if (!s.isFinalCallbackFired())
{
s.doFire();
}
}
}
static class ShortCircuit
{
private boolean fired = false;
boolean isFinalCallbackFired()
{
return fired;
}
void doFire()
{
System.out.println("Calling doFire");
pause(500);
fired = true;
}
}
private static void pause(long ms)
{
try
{
Thread.sleep(ms);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
The output is
Running test without synchronization:
Calling doFire
Calling doFire
Running test with synchronization:
Calling doFire
Running test with wrong synchronization:
Calling doFire
Calling doFire
So the synchonized block does make sure that the doFire method is only called once. But this only works if all modifications are only done in the fureFinalCallback method. If the object is modified elsewhere, without a synchronized block, the doFire method may be called twice.
(I'd like to offer a solution for this, but without details about the ShortCircuit class and the remaining classes and processes, one could only give the vague hint to have a look at the java.util.concurrent package and its subpackages: Locks and Conditions might be a viable path, but you have to figure that out...)

Understanding synchronized on listeners notifiers

I have singleton thread class that sometimes calls function below and notifies listeners from it's thread run() method :
public class Serial implements Runnable
{
private ArrayList observers = new ArrayList();
...
public void run()
{
notifyListeners(new CS());
}
public synchronized void notifyListeners(CS value)
{
log.debug("notifying listeners with Control ");
int os = observers.size();
for (int i = 0; i < observers.size(); i++)
{
MListener observer = (MListener) observers.get(i);
observer.dataReceived(value);
}
}
...
public void addListener(MListener lsn)
{
observers.add(lsn);
}
public void removeListener(MListener lsn)
{
observers.remove(lsn);
}
}
I'm just wondering what gives synchronized on notifyListeners method? One of reasons - not allow add/remove observers from/to ArrayList observers while notifyListeners is called. Please correct me if I'm wrong. What more it might give?
UPD
I have updated my code with two methods addListener and removeListener. I suppose it is mistake since both of these methods are not synchronized and might be called from another thread ?
IMO the synchronization on notify does not make sense. If I understand you correctly, the notify method is only called by your singleton thread.
But your observer implementations content probably might be accessed by different threads. There the access to internal state must be synchronized.
E.g. if you want to save the given value to a member of the observer, which later is used by e.g. the main GUI thread you must synchronize the access to this member:
// called by your notify thread
void dataReceived( CS value)
{
synchronized (this)
{
myValue = value;
}
}
and:
// called by your GUI main thread:
public CS getValue()
{
synchronized (this)
{
// optional check for not null:
if ( myValue == null) throw new IllegalStateException();
logger.debug( "returning value: " + myValue);
return myValue;
}
}
If the CS is an AtomicXY (e.g. AtomicInteger) class, the synchronization is not needed. But if you want to do more than just assigning/returning the value (e.g. some checking or log output) the synchronization is mandatory.
The answer mostly depends on your context because it could be for 2 potential reasons:
We want to protect your list of listeners from concurrent accesses and modifications because it is an ArrayList which is not thread-safe (assuming that that the list can be modified elsewhere in your code and any time it is modified it is protected by a synchronized block with this as object's monitor otherwise it would not be done properly and/or it would be useless).
We want to prevent concurrent notifications for some internal logic.
In your case as you only have one thread that calls notifyListeners #2 should not be the reason unless the code owner assumed that you could have several threads doing this task in the future.
The reason #1 makes sense only if the list of observers can be modified by other threads concurrently if it is not possible you can simply remove the keyword synchronized from your method declaration as it would be useless so it would affect the performances for nothing.
Assuming that #1 is the reason, you should rather use the thread-safe List CopyOnWriteArrayList instead of an ArrayList because it is very efficient in mostly read accesses scenarios which is generally the case of a list of observers that we mostly read and rarely modify, your code would then be something like that:
public class Serial implements Runnable {
private final List<MListener> observers = new CopyOnWriteArrayList<>();
...
public void notifyListeners(CS value) {
log.debug("notifying listeners with Control ");
for (MListener observer : observers) {
observer.dataReceived(value);
}
}
I suppose it is mistake since both of these methods are not
synchronized and might be called from another thread ?
I confirm that the current code is not correct since your list of observers can be modified by concurrent threads thanks to the public methods addListener and removeListener and those methods don't modify your list within a synchronized block with this as object's monitor such that the current code is not thread-safe as it doesn't prevent concurrent accesses to your non thread-safe list.

Java null check

I have one thread1:
if(object != null){
object.play();
}
and another thread2 that can write null into object reference at any time.
I will run these threads at same time. I know thread2 can rewrite object reference after the null check and that will throw NullPointerException. Is it possible for thread2 to rewrite object reference after NullPointerException check?
Is it possible to for thread2 to rewrite object reference after NullPointerException check ?
Absolutely - it could change the value of object while the play() method is executing, if that's what you mean. That wouldn't cause an error in itself.
Note that without synchronization or other memory barriers, thread2 could change the value of object without thread1 noticing for an indeterminate period of time.
It's hard to say what you ought to do, without any other knowledge of the bigger aim of the code.
Simple synchronized example:
/**
To maintain thread safety, only access this through getter and setter
or other synchronized method
**/
private ObjectType object;
public synchronized void setObject(ObjectType object) {
this.object = object;
}
public synchronized ObjectType getObject() {
return object;
}
public void doPlay() {
final ObjectType obj = getObject();
//here, thread 2 can change "object", but it's not going to affect this thread
//as we already safely got our reference to "object" in "obj".
if(obj != null){
obj.play();
}
}
public synchronized void alterativeDoPlay() {
//the difference here is that another thread won't be able to change "object"
//until the object's play() method has completed.
//depending on the code in play, this has potential for deadlocks, where as
//the other `doPlay` has zero deadlock potential.
if(object != null){
object.play();
}
}
If object is an instance variable or a static variable that can be changed from multiple threads, its value can change between the time you test it in the if statement and the time when you call its instance method.
You can modify the code to avoid this problem by copying the object into a local variable, like this:
Playable objectCopy = object;
if(objectCopy != null) {
objectCopy.play();
}
Since objectCopy is a local variable, its value cannot change between the test and the call of play. Of course the state of the playable object itself can change, but that is not something that can be fixed by null checking.
You can use CountDownLatch here. Where Thread1 will wait to count down by Thread2 and you can perform the task in thread2 and stop count down.
Code snippet -
CountDownLatch latch = new CountDownLatch(1);
new Thread1(latch).start();
new Thread2(latch).start();
public class Thread1 extends Thread {
private final CountDownLatch startLatch;
public Thread1(CountDownLatch startLatch) {
this.startLatch = startLatch;
}
public void run() {
try {
startLatch.await();
// ... perform task
} catch (InterruptedException iex) {}
}
}
public class Thread1 extends Thread {
private final CountDownLatch stopLatch;
public Thread1(CountDownLatch stopLatch) {
this.stopLatch = stopLatch;
}
public void run() {
try {
// perform task
} finally {
stopLatch.countDown();
}
}
}
According to Brian's Law :
When we write a variable, which next has to be read by another thread, or when we are reading a variable which has lately been written by another thread, then use synchronization.
Synchronize the atomic statements or getter/setters which has access to the crucial state of data with the same monitor lock.
- Use synchronization.
- You can use CountDownLatch from java.util.concurrent
You will need to use some form of synchronisation primitive to solve this problem. See "Syncrhonised Statements" here. In your case you will need to wrap the whole if block and any places in any threads that use or update object2.
As my professor said: "Concurrency is a pretty unstable guy. We never know what to expect of him." Comming to your question:
Is it possible for thread2 to rewrite object reference after
NullPointerException check?
Yes
Thread2 can access the object many times during 1 occurrence of thread1. Or the other way around. There may be many occurrences of thread1, while thread2 accesses the object.
If you use simple
System.out.println();
in many places in your code, you may notice the output in the console to be displayed AFTER the NullPointerException error(if it wasn't caught).

External call to synchronized function held/locked

The Following class DoStuff starts a thread and syncs to protect the listener object from being accessed when null.
Now when accessing the DoStuff class function setOnProgressListener() externally I'm having issues because the call is getting held for a long time before it exits the function call. I'm not sure why this happens? I seems as if the synchronization has queued up a lot of calls? Any input on this would help!
I'm essentially passing null to the listener because I no longer wish to get updated for this status. I do this as part of my process to kill the DoStuff Thread.
Thanks!
public class DoStuff extends Runnable
{
Object MUTEX = new Object();
private OnProgressListener mOnProgressListener = null;
public DoStuff()
{
new Thread(this).start();
}
public void setOnProgressListener( OnProgressListener onProgressListener )
{
synchronized (MUTEX)
{
mOnProgressListener = onProgressListener;
}
}
private void reportStatus( int statusId )
{
synchronized (MUTEX)
{
if (null != mOnStatusListener)
{
mOnStatusListener.setStatusMessage(new OnStatusEvent(this, statusId));
}
}
}
// this is the run of a thread
public void run()
{
int status = 0;
do
{
// do some work and report the current work status
status = doWork();
reportStatus( status );
} while(true);
}
}
You should use wait/notify. here is sample;
public class DoStuff {
Object MUTEX = new Object();
String data = null;
public void setData(String data) {
synchronized (MUTEX) {
this.data = data;
System.out.println(Thread.currentThread());
MUTEX.notifyAll();
}
}
public void run() {
do {
synchronized (MUTEX) {
if (null == data) {
return;
} else {
System.out.println(data);
}
try {
MUTEX.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} while (true);
}
}
The trouble with this code is that your while() loop is constantly trying to grab the monitor for MUTEX immediately after releasing it or even yield()-ing to help the scheduler put another thread in. So there's a very good chance that anyone else trying to obtain that monitor will be starved, because your while() loop will consume most of your CPU time and even when other threads could run, they might not get the monitor they're waiting for.
Ideally a wait()/notify() pair should be used or failing that, you should at least call a Thread.yield() in your while loop, outside the synchronized block. (But I this second "solution" really isn't a very good one, you should consider using the first one instead.)
UPDATE: I read the code again and I think I believe to see what you wanted to achieve: printing the value of data every time you set a new value. If that's true, you should definitely go for the wait/notify solution, although if you want to absolutely guarantee that every single value is printed, you need to do even more work, possibly using a queue.
I'm a little confused about your code, can you provide the full listing?
First, where does DoStuff start a thread? Why are you quitting if your data is still null? (you might actually be out of the thread before setData even executes).
But the main thing here is that you're doing essentially a busy-waiting loop, in which you synchronize on the mutex. This is pretty wasteful and will generally block cores of your CPU.
Depending on what you are trying to do, you might want to use a wait-notify scheme, in which the thread goes to sleep until something happens.
Thanks all for your help. I was able to determine why the indefinite lock. Something important and obvious is that once I run the reportStatus() function call it will hold the lock MUTEX until it is completely done executing the callback. My fault was that at the registered callback I was calling setOnProgressListener(null) by mistake. Yes, I admit didn't post enough code, and most likely all of you would have catched the bug... So calling setOnProgressListener(null) would wait until the MUTEX object has been released, and the reportStatus() was held waiting to call setOnProgressListener(null), therefore I was in a deadlock!
Again the main point I learned is to remember that triggering a callback message will hold until the registered callback function is done processing it's call.
Thanks all!

Java PriorityQueue Wait

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
}

Categories

Resources