ReentrantLock - Is this a valid approach to using it - java

I have two methods both run by different threads, one of the methods i dont want to run when the other has been called. This is the reason I have chosen to use a lock
#Override
public synchronized void doSomething(int[] params)
{
while (lock.isLocked())
{
// wait for it to become unlocked
}
//lock is released so lets do some stuff
in my other method I have the following implementation
#Override
public void doSomethingElse(int param)
{
lock.lock();
for (int i = 0 ; i < param; i++)
{
//do some stuff
}
lock.unlock();
}
Is the while loop the correct way to say, I want this thread to wait here until the lock is released or is there a better way to implement this
Thanks

The while loop does busy waiting, which is definitely something you don't want to do.
Calling lock.lock(); will block until the lock is released, so it's the proper way to do it, just like you're doing in your other method.
You also don't need for the first method to be synchronized, and the lock should always be released in a finally clause.

You need something like this:
private void method1()
{
lock.lock();
try {
...
} finally {
lock.unlock();
}
}
private void method2()
{
lock.lock();
try {
...
} finally {
lock.unlock();
}
}
Don't forgeet to use try {} finally{} or you could end up with deadlock.

Both wrong, the standard practice is to unlock in the finally clause. Otherwise the application will stall if exception is thrown from inside the code where the lock applies:
public void doSomethingElse(int param) throws Exception {
lock.lock();
try {
//do some stuff that may throw exceptions
} finally {
lock.unlock();
}
}

Related

Wait and Notify on same Thread

Is there anyway one single thread can wait and notify itself to "wake" up, or only
I got something like this but it isnt working and i get the illegalmonitorstateexception
public class test extends Thread{
private int n;
private int lim;
public test(int lim) {
n = 0;
this.lim=lim;
}
public synchronized void add() throws InterruptedException {
n++;
notify();
}
#Override
public void run() {
while(n!=lim){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//do something
}
}
Main
The confusion here appears to be with the idea of "notifying a thread". You don't (usually) call notify, notifyAll or wait of a Thread object. Invoke it any object that you are using as a lock. (A particular problem with Thread is that it is used as a lock for a particular purpose already (Thread.join).)
So you need some kind of lock object:
private final Object lock = new Object();
To wait on the object, you need to hold the lock and the condition should be checked in a while loop.
synchronized (lock) {
while (!some_condition) {
lock.wait();
}
...
}
To notify, hold the lock, notify (you might as well go for notifyAll, it'll be at least as good as notify and sometimes it may be necessary but not caught in testing) and change the condition.
synchronized (lock) {
lock.notifyAll();
some_condition = true;
}
Also, it good practice not to subclass Thread. Goes for other unnecessary subclassing too. Typically you would create a Runnable and pass it to the constructor.
IllegalMonitorStateException means you "don't own the monitor". To do that:
synchronized (this) {
wait()
}
What do you want to trigger the notification? As commented above, if a Thread is waiting, it can't take any action. Maybe you want to use a timeout?
Update:
To wait() until lim is reached, add this to the add() method:
if (n >= lim) {
notify();
}

Pause Thread after a method is called

Basically I want to pause my Thread after I called a method, before continuing to the other one. I can't loop, my method can only be ran once.
The idea behind this, is to be used in a game, where the methods will display messages, and each time a user presses a key, the next message sould be shown. I can't just go through a list, as the game takes input from the user. I looket at Thread.pause() and Thread.resume() but they woN't work either, and are deprecated.
My current code (Which isn't working):
private Thread thread;
private Thread managerThread;
private final Object lock = new Object();
private boolean shouldThreadRun = true;
private boolean storyRunning = true;
public Storyline() {
setUpThread();
}
private void setUpThread() {
managerThread = new Thread(() -> {
while(storyRunning) {
synchronized (lock) {
if(!shouldThreadRun) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Looping");
}
}
});
thread = new Thread(() -> {
synchronized (lock) {
pauseThread();
System.out.print("A");
pauseThread();
System.out.print("B");
}
});
managerThread.start();
thread.start();
}
public void pauseThread() {
shouldThreadRun = false;
}
public void resumeThread() {
shouldThreadRun = true;
}
Take a look at my edits and see if it is any similar to what you were trying to achieve. I'm using a scanner to simulate user input, just press enter on your keyboard to try it out.
By the way I hope this is just an exercise and not a real life situation. You should try to avoid this kind of low level management of multithreading in a real product, unless really necessary, in which case you should still use appropriate data structures meant for this. In a real application buttons will be linked to callbacks and you will set some onClick() method to execute the code you need, as soon as the button is pressed.
For what concerns concurrency, I strongly suggest you to take a look at these tutorials: Oracle-Concurrency
PS: notice that I'm completely ignoring interrupts, which is a bad practice, those exception should be handled the right way: I was just trying to achieve the desired result by keeping the code as simple as possible. Also, like someone else pointed out, you should handle spurious wakeups by just calling the wait inside a loop.
private Thread thread;
private Thread managerThread;
private final Object lock = new Object();
Scanner in;
public Storyline() {
setUpThread();
}
private void setUpThread() {
managerThread = new Thread(() -> {
while(true) {
in = new Scanner(System.in);
in.nextLine();
resumeThread();
}
});
thread = new Thread(() -> {
synchronized (lock) {
while(true){
System.out.print("A");
try {
lock.wait();
} catch (InterruptedException e) {}
System.out.print("B");
try {
lock.wait();
} catch (InterruptedException e) {}
}
}
});
managerThread.start();
thread.start();
}
public void resumeThread() {
synchronized(lock){
lock.notify();
}
}
The first rule of Object.wait, as described in the documentation, is that it must be called in a loop which depends on the condition which is the basis for the wait.
So, your wait needs to look like this:
synchronized (lock) {
while (!shouldThreadRun) {
lock.wait();
}
}
An interrupt is not something that happens by accident. A thread is only interrupted if another thread explicitly asks it to stop what it’s doing and exit cleanly.
Therefore, if you get an interrupt, the correct course of action is not to ignore it and print a stack trace. You need to exit cleanly.
The easiest way to do this is to simply enclose your entire while loop in a try/catch:
try {
while (storyRunning) {
synchronized (lock) {
while (!shouldThreadRun) {
lock.wait();
}
System.out.println("Looping");
}
}
} catch (InterruptedException e) {
System.out.println("Exiting, because someone asked me to stop.");
e.printStackTrace();
}
This way, your while-loop will automatically exit when interrupted.
Lastly, Object.wait is useless unless another thread calls Object.notify or Object.notifyAll on the very same object on which the waiting thread is synchronized. The wait method will (probably) never return unless the object gets a notify:
public void pauseThread() {
synchronized (lock) {
shouldThreadRun = false;
// Tell waiting thread that shouldThreadRun may have changed.
lock.notify();
}
}
public void resumeThread() {
synchronized (lock) {
shouldThreadRun = true;
// Tell waiting thread that shouldThreadRun may have changed.
lock.notify();
}
}
Notice that the synchronizing is inside the methods. If you keep your thread synchronized on lock all the time, the manager thread will never have a chance to run at all, because it’s trying to acquire a synchronization lock on the same object. (However, the opposite is not true; the manager thread can stay synchronized on lock all the time, because the wait() method will temporarily release the synchronization lock, allowing the other thread to proceed.)
If all code which accesses shouldThreadRun is inside synchronized blocks, you don’t need to (and should not) make shouldThreadRun volatile, since the synchronization already ensures multi-threaded consistency.

Is it fine to call this synchronized method from a synchronized block?

Simply put, I'm wondering if this changes the behavior. I'm assuming yes, because calling someMethod() will lock the entire object, instead of just the list object? But I'm still new to this synchronization stuff, so I'd like some more educated feedback.
The before:
public void run() {
int i = 0;
while (!end) {
synchronized (list) {
while (list.size() == i) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
The After:
public void run() {
int i = 0;
while (!end) {
synchronized (list) {
while (list.size() == i) {
someMethod();
}
}
}
}
public synchronized void someMethod() {
try {
list.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
You are correct - the new code has got different semantics, as someMethod() is indeed synchronized on the instance it is being invoked on (and as such, that synchronization is entirely unrelated to the one on list). However, the call to someMethod() will take place while the monitor on list is being held, so a call to run() is "equally thread safe" with respect to list.
On the other hand, you have now introduced the possibility for multiple threads to call someMethod() directly at the same time. You have also introduced a (probably unnecessary) potential for deadlock with other threads due to the extra synchronization on the object itself. I would recommend this instead:
public void someMethod() {
synchronized (list) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
This method is now safe both for individual use and for being called through run() - note that it is safe to synchronize on an object that you have already synchronized on; the thread won't block itself.
With syncronized you don't really 'lock' an object. You will just make sure that access from everyone who is synchronizing on that specific object is 'regulated' with a lock.
A synchronized method is synchronizing on this.
That means, if you enter a syncronized block on some object list you can call a syncronized method without a problem at first
Some things to be thought about:
This code doesn't produce a deadlock:
public void foo() {
synchronized (this) {
someMethod();
}
}
public synchronized void someMethod() {
// ...
}
because you already have the "lock" on this, but this:
public void foo() {
synchronized (list) {
someMethod();
}
}
public synchronized void someMethod() {
// ...
}
may produce a deadlock with some other thread! You'll have to be really careful if you enter a synchronized section within another synchronized section

What is missed signal in java? how calling notify() be missed by the waiting thread?

I was going through one concurrency tutorial by Jakob Jenkov. In this he mentioned sometimes notify() signal can be missed by waiting thread. How is this possible?
public class MissedSignal {
//boolean wasSignalled = false;
public void doWait() {
synchronized (this) {
//if(!wasSignalled){
try {
this.wait();
} catch (InterruptedException e) {
}
//}
}
}
public void doNotify() {
synchronized (this) {
//wasSignalled = true;
this.notify();
}
}
}
I am not able to understand the use of commented part of this code. As i think the notify()signal would never be missed by waiting thread? Could someone please explain... I am new to java and i didn't find answers of this on google.... Thanks in Advance
Signal can be missed if doNotify called before doWait. So doNotify should mark somehow that it was called. The usual way for this is using a variable. Uncomment all usages of wasSignalled and the signal will not be missed.
Hint:
public synchronized void foo() { ... }
is the exact same as
public void foo() { synchronized(this) { ... } }
It is better to use the first version for ease of reading and possible compiler optimizations.

Lightweight long-running method cancel pattern for Java

Is there a lightweight pattern to cancel long running method, which replaces code like this:
public void longComputations() {
... first step...
if ( cancelled ) {
rollbackWork();
return;
}
... second step...
if ( cancelled ) {
rollbackWork();
return;
}
... third step...
if ( cancelled ) {
rollbackWork();
return;
}
}
I know that I can make a Task class, subdivide steps to task objects, make a queue and just do tasks step by steps in loop with cancelation checking, but I'm just wondering is there any simple code-structure pattern for such situation.
I am not aware of such a mechanism. Since you have to track your work in order to be able to perform rollbackWork(), a well-designed object-oriented solution is your best choice anyway, if you want to further evolve this logic! Typically, such a scenario could be implemented using the command pattern, which I still find pretty lightweight:
// Task or Command
public interface Command {
void redo();
void undo();
}
A scheduler or queue could then take care of executing such task / command implementations, and of rolling them back in order.
How about this edit, not a pattern though? Exceptions are very cheap, so it should be fast.
public void caller(){
try{
longComputations();
} catch (MeaningfulRuntimeException e){
rollbackWork(e.getStep());
}
}
public void longComputations() {
... first step...
checkStatus(1);
... second step...
checkStatus(2);
... third step...
checkStatus(3);
}
public void checkStatus(int step){
if ( cancelled ) {
... we may rollback here or throw an exception ...
throw MeaningfulRuntimeException(step);
}
}
If the steps call methods which throw InterruptedException then you can use Thread.interrupt(). You will still need to maintain enough state information to do the rollback properly.
If the steps cannot be interrupted this way, you should not consider relying on the deprecated Thread.stop() mechanism since it is inherently unsafe.
It seems that either way it makes sense to do exactly what you described: encapsulate this workflow logic in a class independent of the computation steps. It should support cancellation and/or interruption and accept a bunch of tasks to be executed. Note that the tasks to be fed into the workflow should provide at least two methods: one to perform the computation and one to roll it back.
You might want to consider using the java.util.concurrent package. You need to wrap your working steps as Callables (or Runnables).
public class InterruptibleTest {
public static void main(String[] args) { try {
final ExecutorService queue = Executors.newFixedThreadPool(1);
queue.submit(new Callable<Void>() { #Override public Void call() { busyWait(1000); return null; } });
queue.submit(new Callable<Void>() { #Override public Void call() { busyWait(1000); return null; } });
queue.submit(new Callable<Void>() { #Override public Void call() { busyWait(1000); return null; } });
final AtomicBoolean cancelled = new AtomicBoolean();
new Thread() { #Override public void run() {
try { Thread.sleep(1500); } catch (InterruptedException ex) { }
queue.shutdownNow();
cancelled.set(true);
}
}.run();
if (cancelled.get()) { rollback(); }
queue.shutdown();
System.out.println("Finished");
} catch (Exception ex) { ex.printStackTrace(System.err); } }
public synchronized static void busyWait(int millis) {
System.out.println("Start");
long until = System.currentTimeMillis() + millis;
while (System.currentTimeMillis() < until) { }
System.out.println("Stopped");
}
public synchronized static void rollback() {
System.out.println("Rollback!");
}
}
Note that shutdownNow() might call interrupt() on the currently executing work thread. You will probably also need to synchronize your rollback() because shutdownNow() returns before non-interruptible code finishes execution.

Categories