This should be an easy problem on multithreading: https://leetcode.com/problems/print-in-order/
"The same instance of Foo will be passed to three different threads. Thread A will call first(), thread B will call second(), and thread C will call third(). Design a mechanism and modify the program to ensure that second() is executed after first(), and third() is executed after second()" And they give this code:
public Foo() {}
public void first(Runnable printFirst) throws InterruptedException {
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
}
public void second(Runnable printSecond) throws InterruptedException {
// printSecond.run() outputs "second". Do not change or remove this line.
printSecond.run();
}
public void third(Runnable printThird) throws InterruptedException {
// printThird.run() outputs "third". Do not change or remove this line.
printThird.run();
}
**Seems I can solve it using Thread.join as below, but what I don't understand is why they pass the instance of Runnable to each method, and how to properly do it because the below code will print each message twice - once because Thread.start() will invoke the corresponding run() method, and once from calling that method directly. I understand that this is the wrong way to do it, but can't figure out what is the right solution, if we try to utilize the join method. **
public Foo() throws InterruptedException {
Runnable r1 = () -> {
System.out.println("first ");
};
first(r1);
Runnable r2 = () -> {
System.out.println("second ");
};
second(r2);
Runnable r3 = () -> {
System.out.println("third ");
};
third(r3);
Thread t1 = new Thread(r1);
t1.start();
try {
t1.join(); // wait for this thread to finish before starting #2
}
catch(Exception e) {
System.err.println("Thread 1 error");
}
Thread t2 = new Thread(r2);
t2.start();
try {
t2.join();
}
catch(Exception e) {
System.err.println("Thread 2 error");
}
Thread t3 = new Thread(r3);
t3.start();
try {
t3.join();
}
catch(Exception e) {
System.err.println("Thread 3 error");
}
}```
A much easier way would be to just use Semaphore with run, acquire, release methods:
class Foo {
Semaphore runSecond;
Semaphore runThird;
public Foo() {
runSecond = new Semaphore(0);
runThird = new Semaphore(0);
}
public void first(Runnable printFirst) throws InterruptedException {
printFirst.run();
runSecond.release();
}
public void second(Runnable printSecond) throws InterruptedException {
runSecond.acquire();
printSecond.run();
runThird.release();
}
public void third(Runnable printThird) throws InterruptedException {
runThird.acquire();
printThird.run();
}
}
Leetcode is for code challenges, so we should not give complete solutions, because that wouldn't then be a challenge for you.
So here's a hint: Use two CountDownLatch objects, one to inform method second() that method first() is done, the other to inform method third() that method second() is done. Read the documentation to learn how to use it.
While you are reading through the documentation, I recommend you read the package documentation, to learn more about what features are available for handling multi-threaded code.
UPDATE
To better understand the challenge, assume that Leetcode is using a class like this to test the Foo class.
public class Test {
public static void main(String[] args) throws Exception {
Foo foo = new Foo();
Thread t1 = new Thread(() -> call(foo::first, "first,"));
Thread t2 = new Thread(() -> call(foo::second, "second,"));
Thread t3 = new Thread(() -> call(foo::third, "third."));
// Start threads out of order, with delay between them, giving each thread
// enough time to complete, if not adequately coded to ensure execution order.
t2.start();
Thread.sleep(500);
t3.start();
Thread.sleep(500);
t1.start();
// Wait for threads to complete
t2.join();
t3.join();
t1.join();
// At this point, the program output should be "first,second,third."
}
interface FooMethod {
public void call(Runnable printFirst) throws InterruptedException;
}
private static void call(FooMethod method, String text) {
try {
method.call(() -> System.out.print(text));
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
You cannot modify this code, as it is hidden from you. You have to somehow add code to the Foo class to ensure the 3 Runnable objects are called in the correct order.
Simply adding Thread.sleep() calls to the 3 methods is not the right solution, since this should run regardless of how long of a delay might be added between thread starts by this test below.
You have to use some kind of thread synchronization feature, e.g. monitors, Locks, or Synchronizers.
Related
I have been assigned an exercise from my uni professor that goes as follow:
"A fence object is an object that has a collection of objects, and can wait on any of those objects is signaled. There is an add(Object) method, which adds an object to the collection. There is also an await() method: this allows to wait on any object of the collection to be signaled. Whenever the add(Object) method is called while the await() method is active, the argument of the add is put in queue. Write the source code using the following interface: ".
public interface Fence {
public void await() throws InterruptedException;
public void add(Object o);
}
So, only when the same number of notify() and objects in queue (aka the number of add(Object) ) are called, the await() terminates and the object in the queue are finally added to the collection. <- this is something I got wrong and realized after writing my code
I did make the implementation as follow:
import java.util.LinkedList;
public class FenceImpl2 implements Fence{
private LinkedList<Object> collection;
private Object mutex; ;
static boolean iswaiting = false;
public FenceImpl2() {
this.collection = new LinkedList<Object>();
this.mutex = new Object();
}
#Override
public void await() throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
synchronized(mutex) {
mutex.wait();
iswaiting = true;
}
} catch (InterruptedException e) {
e.printStackTrace();
}}});
t1.start();
}
#Override
public void add(Object o) {
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
synchronized(mutex){
if(iswaiting == true) {
try {
mutex.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else {
collection.add(o);
}
}}});
t2.start();
}
public Object getList() throws InterruptedException {
synchronized(mutex){
System.out.println("Collection list: \n");
for(Object o : collection) {
System.out.println(o);
Thread.sleep(1000);
}
System.out.println("------- \n");
return collection;
}
}
public void notification() {
Thread thread = new Thread(()->{
synchronized(mutex){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mutex.notify();
}
});
thread.start();
}
public static void main(String[] args) throws InterruptedException {
FenceImpl2 f = new FenceImpl2();
Object o1 = 1;
Object o2 = 2;
Object o3 = 3;
Object o4 = 70;
f.add(o1);
System.out.println("Add 1");
f.add(o2);
System.out.println("Add 2");
f.add(o3);
System.out.println("Add 3");
f.await();
System.out.println("Await active ");
f.add(o4);
System.out.println("Aggiungo 70 - Shouldn't appear. Forced in queue");
f.getList();
f.notification();
System.out.println("Notify() sent - 70 should now appear in the collection");
f.getList();
}
}
After submitting it to my professor I have been told two things:
The synchronization is not correct: the await "unlocks" after the first notify and that shouldn't happen because it doesn't wait for the other (if any) objects that are in queue to be notified.
^Let me say I know how to fix that easily but
Although it's a minor mistake, the methods await, add and notification SHOULD NOT be done using asynchronous dedicated threads.
Here it finally comes my problem. How am I supposed to use wait() on a lock object and then notify() if I am not using dedicated threads?
I tried removing the threads but obviously as soon as I'm calling mutex.wait() the program locks and the code right after that calls the notification method is not reached.
Why did my professor tell me using threads is wrong?
How can I use a wait() and then call a notify() in two separate methods without having the program lock?
Here's an example of what I mean:
public class testw {
private Object mutex;
boolean condition = false;
public testw() {
this.mutex = new Object();
}
public void startWait() {
synchronized(mutex) {
try {
Thread.sleep(1000);
condition = true;
while(condition == true) {
System.out.println("Waiting!");
mutex.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void sendNotify() {
synchronized(mutex) {
try {
Thread.sleep(3000);
System.out.println("Notify!, not waiting anymore");
condition = false;
mutex.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
testw t = new testw();
t.startWait();
t.sendNotify();
}
Without using threads, when I startWait() is called the main thread goes in wait, but there's no way that sendNotify() to be called and the programs freezes. Is there a way to do this without using threads or am I missing something?
Thank you very much.
I have been told...Although it's a minor mistake, the methods await, add and notification SHOULD NOT be done using asynchronous dedicated threads.
The whole point of a method named await() is that it should not return until the event that the caller wants to wait for has happened.
Your await() method doesn't wait. It creates a new thread and then it immediately returns. The new thread waits for something, but after that it just dies without doing anything useful. The new thread might as well not exist at all.
Your add(o) method doesn't make a whole lot of sense either. I'm not even sure what you were trying to do with it, but I think you need to take a step back, and try to explain to the duck why you thought that either of those two methods should create a new thread.
How am I supposed to use wait() on a lock object and then notify() if I am not using dedicated threads?
The Oracle "Guarded Blocks" tutorial is an oldie but a goodie. If you work through it to the end, it should give you a pretty clear idea of how and why and when to use wait() and notify().
https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
In classical Deadlock example, there are two paths in the code acquiring the same two synchronized locks, but in different order like here:
// Production code
public class Deadlock {
final private Object monitor1;
final private Object monitor2;
public Deadlock(Object monitor1, Object monitor2) {
this.monitor1 = monitor1;
this.monitor2 = monitor2;
}
public void method1() {
synchronized (monitor1) {
tryToSleep(1000);
synchronized (monitor2) {
tryToSleep(1000);
}
}
}
public void method2() {
synchronized (monitor2) {
tryToSleep(1000);
synchronized (monitor1) {
tryToSleep(1000);
}
}
}
public static void tryToSleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
This could potentially result in a deadlock. To increase the chance that it actually deadlocks, I am adding those tryToSleep(1000);, just to ensure that method1 will acquire a lock on monitor1, and method2 will acquire the lock on monitor2, before even trying to acquire next lock. So using the sleep this Deadlock simulates "unlucky" timing. Say, there is a strange requirement, that our code should have the potential to result in a deadlock, and for that reason, we want to test it:
// Test
#Test
void callingBothMethodsWillDeadlock() {
var deadlock = new Deadlock(Integer.class, String.class);
var t1 = new Thread(() -> {
deadlock.method1(); // Executes for at least 1000ms
});
t1.start();
var t2 = new Thread(() -> {
deadlock.method2(); // Executes for at least 1000ms
});
t2.start();
Deadlock.tryToSleep(5000); // We need to wait for 2s + 2s + some more to be sure...
assertEquals(Thread.State.BLOCKED, t1.getState());
assertTrue(t1.isAlive());
assertEquals(Thread.State.BLOCKED, t2.getState());
assertTrue(t2.isAlive());
}
This passes, which is good. Which is not good is that I had to add sleep into the Deadlock class itself, and also in its test. I had to do this just in order to make the test consistently pass. Even though if I remove sleep from everywhere this code could sometimes produce a deadlock, but then there is no guarantee that it happens during the test. Now say having sleep is unacceptable here, then the question is:
How can I reliably test that this code, has a potential to cause a deadlock without any sleep neither in the test and in the actual code itself?
edit: I just wanted to emphasize that I am asking for the class to have a potential for a deadlock, only in some "unlucky" timing (when two threads are calling method1() and method2() at the same time) this deadlock should happen. And in my test, I want to demonstrate deadlock on every run. I want to remove sleep calls from the production code (hopefully from the test also). Maybe there is a way to use mocks instead of the injected monitors, so we could orchestrate them acquiring locks in a specific order during the test?
Essentially, you need Thread (t1) executing method1 to wait inside synchronized (monitor1) but outside ofsynchronized (monitor1) until another Thread (t2) executing method2 goes inside synchronized (monitor2) and releases t1 and both threads try to proceed.
Or vice versa, where t2 waits until t1 comes and releases
You can code this scenario yourself. But since you are focusing just on Deadlock testing, you can use a java.util.concurrent.CyclicBarrier between 2 parties to orchestrate this, where parties indicate the number of threads that must invoke CyclicBarrier.await() before the barrier is tripped (in other words, all the threads previous awaiting proceeds).
class Deadlock {
final private CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
final private Object monitor1;
final private Object monitor2;
public Deadlock(Object monitor1, Object monitor2) {
this.monitor1 = monitor1;
this.monitor2 = monitor2;
}
public void method1() throws BrokenBarrierException, InterruptedException {
synchronized (monitor1) {
cyclicBarrier.await();
synchronized (monitor2) {
}
}
}
public void method2() throws BrokenBarrierException, InterruptedException {
synchronized (monitor2) {
cyclicBarrier.await();
synchronized (monitor1) {
}
}
}
public static void tryToSleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
You will have to handle the checked Exceptions threw by cyclicBarrier.await()
Thread t1 = new Thread(() -> {
try {
deadlock.method1();
} catch (BrokenBarrierException | InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
Thread t2 = new Thread(() -> {
try {
deadlock.method2();
} catch (BrokenBarrierException | InterruptedException e) {
e.printStackTrace();
}
});
t2.start();
deadlock.tryToSleep(5000); // Wait till all threads have a chance to become alive
assertEquals(Thread.State.BLOCKED, t1.getState());
assertTrue(t1.isAlive());
assertEquals(Thread.State.BLOCKED, t2.getState());
assertTrue(t2.isAlive());
I don't know how to make for a thread to run until the task is finished.
So i have this class:
public class MainTest {
public static void main(String[] args){
ThreadRunnable t1 = new ThreadRunnable();
Thread t2 = new Thread(t1);
t2.start();
System.out.println(3);
//here the next code to run
}
}
And another that try for example to add data in database:
public class ThreadRunnable implements Runnable{
public void run(){
//code to make the thread waits until the insert is done
//code for inserting data in database
}
}
So, inside method run() i want something like:
- try to insert data in database
- if connection to database is down, wait 5 seconds and try again
- if connection is ok, then insert data, and return successful message that data is added
Is this possible, and if yes, how?
Thanks!
You don’t need to wait for a thread. Just do the retries in a loop in your Runnable:
public void run() {
try {
while (true) {
try {
// Do database operations here
// Succeeded
break;
} catch (SQLException e) {
// Failed; log exception and try again.
logger.log(Level.INFO, "Couldn't save data.", e);
}
// Wait before trying again.
Thread.sleep(5000);
}
} catch (InterruptedException e) {
logger.log(Level.INFO, "Interrupted; exiting.", e);
}
}
Note: An interrupt is an explicit request for a thread to stop what it’s doing and self-terminate. The InterruptedException should not be caught inside the loop, because you want the loop to terminate in the event of an interrupt.
On the other hand, you do want the loop to keep executing in the event of an SQLException, so it should be caught inside the loop.
You can do something like that :
1) Add a waitFor function in your ThreadRunnable
2) Add synchronization via un LOCK variable
The code :
public class ThreadRunnable implements Runnable{
private boolean ended=false;
private final Object LOCK=new Object();
public void run(){
// do my stuff...
...
//at the end, notify the thread waiting for : it will wake up
synchronized(LOCK)
{
ended=true;
LOCK.notifyAll();
}
}
/**
Waits until the task is done
*/
public void waitFor()
{
synchronized(LOCK)
{
while(!ended)
{
//sleeps until notifAll is called (see run())
wait();
}
}
}
}
(in this code, you have to add the try/catch for the InterruptedException)
In your main :
public class MainTest {
public static void main(String[] args){
ThreadRunnable t1 = new ThreadRunnable();
Thread t2 = new Thread(t1);
t2.start();
t1.waitFor();
System.out.println(3);
//here the next code to run
}
}
How can I notify Thread t1 and Thread t2 at the same time (so it is the same probability to get hey 1 as hey2 first)? I've tried notifyAll, but couldn't make it work.
class Thr extends Thread
{
Thr () throws InterruptedException
{
Thread t1 = new Thread() {
public synchronized void run()
{
while (true)
{
try {
wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try
{
Thread.sleep(1500);
} catch (Exception e) { }
System.out.println("hey 1");
}
}
};
Thread t2 = new Thread() {
public synchronized void run()
{
while (true)
{
try {
wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try
{
Thread.sleep(1500);
} catch (Exception e) { }
System.out.println("hey 2");
}
}
};
t1.start();
t2.start();
}
public static void main(String args[]) throws InterruptedException
{
new Thr();
}
}
You should wait on a shared object and use notifyAll as in:
class Thr extends Thread
{
Thr () throws InterruptedException
{
final Object lock = new Object ();
Thread t1 = new Thread() {
public void run()
{
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("hey 1");
}
};
Thread t2 = new Thread() {
public synchronized void run()
{
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("hey 2");
}
};
t1.start();
t2.start();
synchronized (lock) {
lock.notifyAll ();
}
}
public static void main(String args[]) throws InterruptedException
{
new Thr();
}
}
The right way to do this is to use notifyAll. The real problem with your code seems to be that you have two threads waiting for notifications on different mutexes. You need them to wait on a single object ... as described in #ShyJ's answer.
Note that there is NO WAY that you can code this so that the notification is guaranteed to be delivered first to either thread with equal probability:
The Java threading specs make no guarantees of fairness in wait / notify.
The thread scheduler implemented (typically) at the OS-level (typically) makes no such guarantees either.
The point is that the application has no control over this. The best approach is to just let wait/notifyAll do what they normally do, and design your application so that any bias in the thread scheduling does not affect the application's behaviour in an important way.
(FWIW, the usual problem is that people explicitly or implicitly assume non-randomness ... and get burned when threads get scheduled in an unexpectedly random order.)
I highly recommend avoiding the use of wait/notify and use something more robust. The problem is that using wait/notify in any combination will likely result in a race condition.
The only way to give equal probability to them academically is to create two Semaphore objects, have the threads try to acquire them, and use Random to choose which one to release first. Even then, if the scheduler decides to run the first one that tried to obtain the lock, then you get bias there anyway, regardless of whether or not the Sempahore is fair. This forces you to wait until the first thread is done before running the second, such as via Thread.join.
Bottom line, the only way to guarantee order in a concurrent system is to force them into a single-threaded format, which throws out the whole point of having them concurrent in the first place.
If you are using Java versions greater than 1.4, then it would greatly simplyfy your task by using any of the concurrent locks:
java.util.concurrent.locks specially the ReadWrite type.
For now for message passing to all the threads at the same type - implement Observer Pattern
/*
This should always produce 0 as output since all three methods increment(), decrement(), value() are thread safe(synchronized). but it is returning 1
*/
class Counter implements Runnable {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
public void run() {
try {
this.increment();
Thread.sleep(1000);
this.decrement();
Thread.sleep(1000);
this.increment();
Thread.sleep(1000);
this.decrement();
Thread.sleep(1000);
}
catch (InterruptedException e){
return;
}
}
public static void main(String args[]) throws InterruptedException {
Counter c = new Counter();
new Thread(c).start();
new Thread(c).start();
System.out.println(c.value());
}
}
like everyone else said you need to make sure that the treads have finished executing, to do that you need to call join. for example
public static void main(String args[]) throws InterruptedException {
Counter c = new Counter();
Thread t1 = new Thread(c).start();
Thread t2 = new Thread(c).start();
t1.join();
t2.join();
System.out.println(c.value());
}
that should run correctly
There's nothing to control when the main thread is calling value(). It will run as soon as it can acquire a lock on c, even though the other threads are still running.
If you want to wait until the threads are done, call join() on them.
You are reading the value before the threads have finished execution, so it may be well different from zero.
You're not waiting for the threads to complete running, so the result is that the value of c is printed at whatever it is at that second. I bet if you tried it 1000 times, there would be times when it wasn't 1.
IBM has a fair tutorial on the situation you're encountering:
http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=/rzahw/rzahwex3rx.htm