Reentrance Lock Condition - java

public class MyLockConditionTest {
private final Lock alock = new ReentrantLock();
private final Condition condition = alock.newCondition();
private String message = null;
public void waitForCallback() {
alock.lock();
try {
// wait for callback from a remote server
condition.await();
doSomething(message);
} finally {
alock.unlock();
}
}
// another thread will call this method as a callback to wake up the thread called condition.await()
public void onCallbackReceived(String message) {
alock.lock();
try {
this.message = message
condition.signal();
} finally {
alock.unlock();
}
}
}
I have this code using ReentrantLock and Condition to implement a class to wait on certain callbacks from a remote server. I tested this code and seems working but I have a few questions.
Why do I need to do alock.lock() / unlock() in onCallbackReceived(). Without calling lock() / unlock(), I was getting an IllegalState exception. I am confused because the lock is held by the caller of waitForCallback() when onCallbackReceived() invoked by another thread so alock.lock() in onCallbackReceived() will always fail.
Do I need to wrap condition.await() in waitForCallback() with while loop?
while(message==null)
condition.await();

Why do I need to do alock.lock() / unlock() in onCallbackReceived(). Without calling lock() / unlock(), I was getting an IllegalState exception.
You are trying to signal a condition in which you do not own the lock. The only way you would hold the lock is if onCallbackReceived is called from doSomething which there is no indication that is occurring.
Do I need to wrap condition.await() in waitForCallback() with while loop?
Yes, imagine you have 5 threads stopped on the condition and 5 threads blocked on lock. Only one thread can wake up. What if when a waiting thread finally wakes up another thread had null'd that field out? You will need to check again to ensure the predicate is still true.

Related

How to make a thread wait without using wait() nor sleep() in java

I am writing a class called MyReentrantLock and I have to create a function called acquire() that locks a thread if it's not locked and if it is indeed locked then it has to wait until it unlocks to lock it again. It's kind of confusing and I can't use wait() or sleep(), only AtomicBoolean and Thread class in java.
public class MyReentrantLock implements Lock{
AtomicBoolean locked = new AtomicBoolean(false);
long IdOfThreadCurrentlyHoldingLock;
#Override
public void acquire() {
if(!locked.compareAndSet(false,true)){
WHAT DO I WRITE HERE!!
}
locked.compareAndSet(false, true);
IdOfThreadCurrentlyHoldingLock=Thread.currentThread().getId();
}
#Override
public boolean tryAcquire() {
if(!locked.compareAndSet(false,true))
return false;
else {
acquire();
return true;
}
}
#Override
public void release() {
locked.compareAndSet(true,false);
if(!locked.compareAndSet(true,false) || IdOfThreadCurrentlyHoldingLock!=Thread.currentThread().getId()){
throw new IllegalReleaseAttempt();
}
}
Replace your if with a while. You may keep the body empty, even though it might be advisable to sleep some milliseconds.
The reason is: Your method acquire neither throws an exception nor does it return a result (success/failure). Thus the calling code would assume when the call to acquire is done, the thread can continue doing the sensitive job.
So you cannot exit the method without having the lock, even if that means to wait indefinitely. A more advanced method would allow to define a timeout but then also needs to communicate whether the lock is aquired or the timeout was reached.

Best way to block other threads until one is finished

I have many threads which monitor a certain state. If the application gets into that state, then I need to do some extra work. I want to allow just 1 thread to execute that and want to block the others until that work is finished. Blocking mean, that they must not execute that task again.
I have the following scenario:
ReentrantLock lock = new ReentrantLock
void doSomething() {
if (lock.tryLock()) {
try {
doSomeWork()
} finally {
lock.unLock()
}
} else {
// wait for DoSomeWork is done
}
}
I can monitor lock.isLocked() in a loop, but actually I just want to have some sort of wait until the work is finished by the other thread.
According to documentation about ReentrantLock class:
It is recommended practice to always immediately follow a call to
lock with a try block, most typically in a before/after construction
such as:
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}
From the documentation for lock() method:"If the lock is held by another thread then the current thread becomes disabled for thread scheduling purposes and lies dormant until the lock has been acquired" and this is what you want to be guaranteed in your scenario.

How to start & stop thread [duplicate]

I wrote a thread, it is taking too much time to execute and it seems it is not completely done. I want to stop the thread gracefully. Any help ?
The good way to do it is to have the run() of the Thread guarded by a boolean variable and set it to true from the outside when you want to stop it, something like:
class MyThread extends Thread
{
volatile boolean finished = false;
public void stopMe()
{
finished = true;
}
public void run()
{
while (!finished)
{
//do dirty work
}
}
}
Once upon a time a stop() method existed but as the documentation states
This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior.
That's why you should have a guard..
The bad part about using a flag to stop your thread is that if the thread is waiting or sleeping then you have to wait for it to finish waiting/sleeping. If you call the interrupt method on the thread then that will cause the wait or sleep call to be exited with an InterruptedException.
(A second bad part about the flag approach is that most nontrivial code is going to be utilizing libraries like java.util.concurrent, where the classes are specifically designed to use interruption to cancel. Trying to use the hand rolled flag in a task passed into an Executor is going to be awkward.)
Calling interrupt() also sets an interrupted property that you can use as a flag to check whether to quit (in the event that the thread is not waiting or sleeping).
You can write the thread's run method so that the InterruptedException is caught outside whatever looping logic the thread is doing, or you can catch the exception within the loop and close to the call throwing the exception, setting the interrupt flag inside the catch block for the InterruptedException so that the thread doesn't lose track of the fact that it was interrupted. The interrupted thread can still keep control and finish processing on its own terms.
Say I want to write a worker thread that does work in increments, where there's a sleep in the middle for some reason, and I don't want quitting the sleep to make processing quit without doing the remaining work for that increment, I only want it to quit if it is in-between increments:
class MyThread extends Thread
{
public void run()
{
while (!Thread.currentThread().isInterrupted())
{
doFirstPartOfIncrement();
try {
Thread.sleep(10000L);
} catch (InterruptedException e) {
// restore interrupt flag
Thread.currentThread().interrupt();
}
doSecondPartOfIncrement();
}
}
}
Here is an answer to a similar question, including example code.
You should not kill Thread from other one. It's considered as fairly bad habit. However, there are many ways. You can use return statement from thread's run method.
Or you can check if thread has already been interrupted and then it will cancel it's work. F.e. :
while (!isInterrupted()) {
// doStuff
}
Make a volatile boolean stop somewhere. Then in the code that runs in the thread, regularly do
if (stop) // end gracefully by breaking out of loop or whatever
To stop the thread, set stop to true.
I think you must do it manually this way. After all, only the code running in the thread has any idea what is and isn't graceful.
You need to send a stop-message to the Thread and the Thread itself needs to take action if the message has been received. This is pretty easy, if the long-running action is inside loop:
public class StoppableThread extends Thread {
private volatile boolean stop = false;
public void stopGracefully() {
stop = true;
}
public void run() {
boolean finished = false;
while (!stop && !finished) {
// long running action - finished will be true once work is done
}
}
}
For a thread to stop itself, no one seems to have mentioned (mis)using exception:
abstract class SelfStoppingThread extends Thread {
#Override
public final void run() {
try {
doRun();
} catch (final Stop stop) {
//optional logging
}
}
abstract void doRun();
protected final void stopSelf() {
throw new Stop();
}
private static final class Stop extends RuntimeException {};
}
A subclass just need to override doRun() normally as you would with a Thread, and call stopSelf() whenever it feels like it wants to stop. IMO it feels cleaner than using a flag in a while loop.

Semaphore with queues

Semaphore:
public void enter() throws InterruptedException {
synchronized (block) {
++current;
if (current > permits) {
try {
block.wait();
} catch (InterruptedException e) {
throw e;
}
}
}
}
public void realese() {
synchronized (block) {
--current;
block.notify();
}
}
How to make a queue in the semaphore? I want threads to be executed in the order of calling the enter().
Here's one way:
Have the release() method wake up every waiting thread (i.e., block.notifyAll())
In the enter() method, have each waiting thread look at the head of the queue.
If the thread at the head of the queue is the current thread, pop the queue and complete the enter() call, -OR-
Go back to waiting otherwise.
But there's a subtle problem that I'll leave to you to work out how to fix:
If thread A wakes up, finds itself at the head of the queue, pops the queue and returns,
Then, thread B could wakes up, finds its self at the head of the queue, and it also pops the queue and returns.
And there you have one release() call which just allowed two threads to enter().
That would be bad. So, you'll need to figure out a way to guarantee that no more than one thread can complete the enter() call each time release() is called.
If your using a newer java you can just add a fairness setting to the constructor.
Semaphore(int permits, boolean fair)
like this
private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);

Best practice for Threads manipullation and Thread destroy?

I am using Threads (still..) for many stuff right now. I found many methods of thread that I would most likely use marked as deprecated.
Is there any chance to pause/resume thread with some triggers? Most people say to use wait.. but if I don't know the time ? I have some events that can happen after 5 minutes or after 2 hours...
Also .. another thing.
If I have a Thread .. it has an run() method. Now the Thread is started , run does what it has to do and then the Thread dies. Like forever ? The stuff from run() method is done so the Thread is ready to be taken out by garbage collector or is it just in some phase of disabled but still existing ?
Now you have a run method like that :
public void run(){
while(running){
//do stuff...
}
}
If I switch the running to false, run method loops and stops because there is nothing more to do . Does this thread also die ? Can I for example say after some time I want to rerun this thread, so I just set the running to true again and call the run method, or do I have to recreate the Thread once again ?
A Thread can only "live" once. When you create a Thread, you specify a Runnable instance as a target (if you don't, the thread targets itself—it implements Runnable and its default run() method does nothing). In either case, when the thread completes the run() method of its target Runnable, the thread dies.
In the example posed in the question, setting running to true after the run() method has returned will do nothing; the Thread can't be restarted after dying.
If you want to pause a thread, and reuse it later, there are a number of mechanisms. The most primitive is wait() and notify(). Rather than waiting for a specified period of time, you wait until a condition changes, like this:
abstract class Pausable implements Runnable {
private final Object lock = new Object();
private boolean pause = false;
abstract void doSomething();
#Override
public void run() {
while (cantering()) doSomething();
}
private boolean cantering() {
synchronized (lock) {
while (pause) {
try { lock.wait(); }
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
return false;
}
}
}
return true;
}
final void whoa() {
synchronized(lock) {
pause = true;
}
}
final void giddyup() {
synchronized(lock) {
pause = false;
lock.notify();
}
}
}
That's a lot of code, and it's fragile. I've been writing Java for 20 years and I'm not sure I got it right. That's why you should use the right tool from java.util.concurrency. For example, if you are waking up the thread to process a message, use a BlockingQueue, and let the consuming thread wait for messages to arrive on the queue. If you have tasks you want to perform asynchronously in response to some event, create an ExecutorService and submit the tasks. Even if you do want to use something like wait()/notify(), the concurrency package's Condition class gives you a lot more control over locking than intrinsic locks offer.
Can I [...] and call the run method?
If you have a Thread t = ...;, and you write a call to t.run(), you probably are making a mistake.
A Thread is not a thread. A thread is a path of execution through your code. A Thread is an object with methods that can be used to create a new thread and manage its life-cycle.
You create the new thread by calling t.start().
Remember this mantra:
The start() method is the method that the library provides for your code to call when you want to start a new thread.
The run() method is the method that your code provides for the library to call in the new thread.

Categories

Resources