Conditional code synchronization only for specific threads - java

Assume that there are three groups of thread. lets say A,B, and C.
I want to create a code block in a method that blocking occurs between A and B type threads , C threads are allowed in all cases of the method invocation including the blocking portion.
In other words, if a A type of thread is in a blocked code portion, B is blocked but C is not blocked.
Do you have an idea if it is possible to do it? If so how this could be done?

You could have helper locking methods :
private final ReentrantLock mLock = new ReentrantLock();
void conditionalLock() {
ThreadGroup group = Thread.currentThread().getThreadGroup();
if (group.equals(groupA) || group.equals(groupB)) {
mLock.lock();
}
}
Edit changed/simplified condition as nicely suggested by erickson
void conditionalUnlock() {
if (mLock.isHeldByCurrentThread()) {
mLock.unlock();
}
}
Then, in the method of the same class :
conditionalLock();
try {
// block you want to synchronize between threads of group A & B
} finally {
conditionalUnlock();
}

Maybe thats a ugly way to do it, but i have an idea.
You could name Your Threads and do an if statment checking the name (type of Thread).
if (Thread.currentThread().getName().contains("A") || Thread.currentThread().getName().contains("B")){
synchronized(this){
//do stuff
}
}else{
//do stuff or even check if its type C
}

Related

Java Threading Cyclic Notify() and Wait()

I'm having a code in Java where two objects wait and notify each other when one finished processing. I'll keep my code simple with the following example and assuming there are no syntax error (I just want you to know the logic is more important here rather than the syntax).
Assuming I have object A which is a thread having this pseudo code
class A is Thread {
run() {
while(true) {
wait(); // wait for signal from B
// then do something if signal received
B.signal(); // let B know that we're done and wait again
}
}
}
Then we have here B which is also a thread having this pseudo code
class B is Thread {
run() {
while(true) {
// Do something
A.signal(); // Let A know to continue processing
wait(); // Wait for signal from A before doing something again
}
}
}
So as you can see there's a cycle. The problem is I am having a dead-lock and the reason here is because when A is finished processing, it signals B to work before it waits.. But by the time B is notified, there are chances that A still haven't reached the wait() code and B is already calling A.signal() and leads to a dead lock.
How do I properly solve this problem? The solution I have in mind is that when B is notified to work, I will let the thread of B sleep for a number of milliseconds but I don't think this is ever a good idea. Any help is appreciated, thanks in advance.
When you use notify() this should be associated with a state change.
When you use wait() this should be associated with a check for a state change.
In real code, you should only wait when you are waiting for something.
Note: wait() can wake spuriously, it doesn't mean notify() was called. As you noticed, notify() does nothing if nothing is wait()ing.
Instead of using this pattern, you can use a BlockingQueue to pass work/messages between threads. This has the wait/notify and the object containing work built in.
However, since you normally need a thread to do the work, there is an ExecutorService builtin to do this. This allows you to pass work to a pool of threads and collect the results.
In short, you should be using an ExecutorService.
If A is using the result of B, then maybe you can consider a BlockingQueue.
As you can find described in the Javadoc, you need to put your wait calls inside a loop that checks for a condition. Otherwise, if you don't have a condition variable or expression that you can check, it is possible that you miss the notify because you were not waiting at that point.
Also, as others have pointed out, you need to hold the monitor of the object you are calling the wait or notify method on; that's what the synchronized keyword is for.
In the below fix, the condition is very simple; it's a variable called notified in classes A and B.
Also, to get this right, A and B need to know about each other. In your code you seemed to be invoking static methods; but the notify method needs to be called on an instance, so you need to keep references to the instances of A and B in B and A, respectively.
This fixes the problems:
class A is Thread {
private B b;
private boolean notified;
public void run() {
while(true) {
synchronized(this) {
while (!notified) {
try {
wait(); // wait for signal from B
} catch (InterruptedException e) {}
}
notified = false;
}
synchronized(b) {
// then do something if signal received
b.notified = true;
b.notify(); // let B know that we're done and wait again
}
}
}
}
class B is Thread {
private A a;
private boolean notified;
public void run() {
while(true) {
synchronized(a) {
// Do something
a.notified = true;
a.notify(); // Let A know to continue processing
}
synchronized(this) {
while (!notified) {
try {
wait(); // Wait for signal from A before doing something again
} catch (InterruptedException e) {}
}
notified = false;
}
}
}
}

Waiting for an object to be initialized

I have an object that is being initialized in a separate thread. Initialization can take several seconds while a local DB is being populated.
SpecialAnalysis currentAnalysis = new SpecialAnalysis(params_here);
I'm trying to implement a "cancel" button, that sets the object's isCancelled boolean to true. What is the proper Java way to implement this?
while (currentAnalysis == null) {
}
currentAnalysis.cancel();
This method freezes the program as it appears to have entered a computationally inefficient loop. Is this a case where I could use Object.wait()?
My current bad/semi-successful solution is:
while (currentAnalysis == null) {
Thread.sleep(500);
}
currentAnalysis.cancel();
Thanks!
Firstly, yes Object.wait() and Object.notify() / Object.notifyAll() are what you need. Whether or not you use them directly is a different matter. Due to the ease of making mistakes programming directly with wait/notify it is generally recommended to use the concurrency tools added in Java 1.5 (see second approach below).
The traditional wait/notify approach:
Initialisation:
synchronized (lockObject) {
SpecialAnalysis currentAnalysis = new SpecialAnalysis(params_here);
lockObject.notifyAll();
}
In the 'cancel' thread:
synchronized (lockObject) {
while (currentAnalysis == null) {
try { lockObject.wait(); }
catch Exception(e) { } // FIXME: ignores exception
}
}
currentAnalysis.cancel();
Of course these could be synchronized methods instead of blocks. Your choice of lockObject will depend on how many 'cancel' threads you need etc. In theory it could be anything, i.e. Object lockObject = new Object(); as long as you are careful the correct threads have access to it.
Note that it is important to put the call to wait() in a while loop here due to the possibility of spurious wakeups coming from the underlying OS.
A simpler approach would be to use a CountDownLatch, sparing you from the nuts and bolts of wait()&notify():
(I'm making a couple of assumptions here in order to suggest a possibly cleaner approach).
class AnalysisInitialiser extends Thread {
private CountDownLatch cancelLatch = new CountDownLatch(1);
private SpecialAnalysis analysis = null;
#Override
public void run() {
analysis = new SpecialAnalysis(params);
cancelLatch.countDown();
}
public SpecialAnalysis getAnalysis() {
cancelLatch.await();
return analysis;
}
}
Then in the thread that needs to send the cancel signal: (obviously you need to get hold of the AnalysisInitialiser object in some way)
analysisInit.getAnalysis.cancel();
No concurrency primitive boilerplate, yay!
i like this question so voted up..
you can do like below
do {
if(currentAnalysis != null){
currentAnalysis.cancel();
}
}
while (currentAnalysis == null)
here your do keeps checking the value of currentAnalysis and once its not null then it performs cancel else keeps looping and checking currentAnalysis value.
this is one better approach i am finding right now

what does it mean when we say synchronized(instance field)..?

Attached the code..
what does this mean, synchronized(m)..?? why we should use that..??
What's the difference between synchronized(this) & synchronized(m)..??
class Waiter implements Runnable {
Message m;
public Waiter(Message m) {
this.m = m;
}
#Override
public void run() {
String name = Thread.currentThread().getName();
synchronized (m) {
try {
System.out.println("Waiting to get notified at time " +System.currentTimeMillis());
m.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("Waiter thread notified at time "+System.currentTimeMillis());
System.out.println("Message processed ");
}
}
}
The difference between synchronized(this) and synchronized(m) is that by synchronizing on this, you synchronize on the entire instance. So, as you would expect, no body would be able to synchronize on this while you hold the lock.
public synchronized void foo() {
// Handle shared resource
}
is similar to
public void foo() {
synchronize(this) {
// Handle shared resource
}
}
By using objects, such as m, you get a more fine grained control over what you want to synchronize and when. But remember that if someone uses foo(), as shown above, it will not stop access to methods that are not synchronized on this:
public void anotherLock() {
synchronized(m) {
// Should handle another shared resource
// otherwise you might get unexpected results
}
}
While a thread is using foo(), another thread can access anotherLock().
The java keyword synchronized is used to synchronize different threads by one instance, acting as a mutual exclusive semaphore. Hence, the argument passed to synchronized is the instance which can be owned by one thread exclusively. It is up to you, the programmer, on which instance you like to synchronize your threads.
But it is a good idea to use the resource, which is under racing conditions, or the owning instance of that resource. The later you start a synchronized block and the earlier you leave it, the better your application will scale.
synchronized is used for thread safety. In your case it is used for implementing observer pattern. you want to wait for something to happen on Message object and then only process it so someone will notify on Message object m for which you are waiting (m.wait()).
When you wait on some object you need to take lock on that object for which you always need to put the wait() statement in a synchronized block on wait object. That is why you are using synchronized(m).
You can not replace it with synchronized(this) as you are calling wait() on object m so synchronized should be on m only.
Somewhere in your application you must be calling m.notify() or m.notifyAll() which will resume your wait() on m.

Java - threads + action

I'm new to Java so I have a simple question that I don't know where to start from -
I need to write a function that accepts an Action, at a multi-threads program , and only the first thread that enter the function do the action, and all the other threads wait for him to finish, and then return from the function without doing anything.
As I said - I don't know where to begin because,
first - there isn't a static var at the function (static like as in c / c++ ) so how do I make it that only the first thread would start the action, and the others do nothing ?
second - for the threads to wait, should I use
public synchronized void lala(Action doThis)
{....}
or should i write something like that inside the function
synchronized (this)
{
...
notify();
}
Thanks !
If you want all threads arriving at a method to wait for the first, then they must synchronize on a common object. It could be the same instance (this) on which the methods are invoked, or it could be any other object (an explicit lock object).
If you want to ensure that the first thread is the only one that will perform the action, then you must store this fact somewhere, for all other threads to read, for they will execute the same instructions.
Going by the previous two points, one could lock on this 'fact' variable to achieve the desired outcome
static final AtomicBoolean flag = new AtomicBoolean(false); // synchronize on this, and also store the fact. It is static so that if this is in a Runnable instance will not appear to reset the fact. Don't use the Boolean wrapper, for the value of the flag might be different in certain cases.
public void lala(Action doThis)
{
synchronized (flag) // synchronize on the flag so that other threads arriving here, will be forced to wait
{
if(!flag.get()) // This condition is true only for the first thread.
{
doX();
flag.set(true); //set the flag so that other threads will not invoke doX.
}
}
...
doCommonWork();
...
}
If you're doing threading in any recent version of Java, you really should be using the java.util.concurrent package instead of using Threads directly.
Here's one way you could do it:
private final ExecutorService executor = Executors.newCachedThreadPool();
private final Map<Runnable, Future<?>> submitted
= new HashMap<Runnable, Future<?>>();
public void executeOnlyOnce(Runnable action) {
Future<?> future = null;
// NOTE: I was tempted to use a ConcurrentHashMap here, but we don't want to
// get into a possible race with two threads both seeing that a value hasn't
// been computed yet and both starting a computation, so the synchronized
// block ensures that no other thread can be submitting the runnable to the
// executor while we are checking the map. If, on the other hand, it's not
// a problem for two threads to both create the same value (that is, this
// behavior is only intended for caching performance, not for correctness),
// then it should be safe to use a ConcurrentHashMap and use its
// putIfAbsent() method instead.
synchronized(submitted) {
future = submitted.get(action);
if(future == null) {
future = executor.submit(action);
submitted.put(action, future);
}
}
future.get(); // ignore return value because the runnable returns void
}
Note that this assumes that your Action class (I'm assuming you don't mean javax.swing.Action, right?) implements Runnable and also has a reasonable implementation of equals() and hashCode(). Otherwise, you may need to use a different Map implementation (for example, IdentityHashMap).
Also, this assumes that you may have multiple different actions that you want to execute only once. If that's not the case, then you can drop the Map entirely and do something like this:
private final ExecutorService executor = Executors.newCachedThreadPool();
private final Object lock = new Object();
private volatile Runnable action;
private volatile Future<?> future = null;
public void executeOnlyOnce(Runnable action) {
synchronized(lock) {
if(this.action == null) {
this.action = action;
this.future = executor.submit(action);
} else if(!this.action.equals(action)) {
throw new IllegalArgumentException("Unexpected action");
}
}
future.get();
}
public synchronized void foo()
{
...
}
is equivalent to
public void foo()
{
synchronized(this)
{
...
}
}
so either of the two options should work. I personally like the synchronized method option.
Synchronizing the whole method can sometimes be overkill if there is only a certain part of the code that deals with shared data (for example, a common variable that each thread is updating).
Best approach for performance is to only use the synchronized keyword just around the shared data. If you synchronized the whole method when it is not entirely necessarily then a lot of threads will be waiting when they can still do work within their own local scope.
When a thread enters the synchronize it acquires a lock (if you use the this object it locks on the object itself), the other will wait till the lock-acquiring thread has exited. You actually don't need a notify statement in this situation as the threads will release the lock when they exit the synchronize statement.

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!

Categories

Resources