I was given following code snippet:
public class ThreadTest{
private static class Thread01 extends Thread{
private Thread02 _th2;
public int foo = 0;
public void setThrd02(Thread02 thrd2){
_th2 = thrd2;
}
public void run(){
try{
for(int i=0;i<10;i++) foo += i;
synchronized(this){this.notify();};
synchronized(_th2){_th2.wait();};
System.out.print(" Foo: " + _th2.foo);
}catch(InterruptedException ie){ ie.printStackTrace();}
}
}
private static class Thread02 extends Thread{
private final Thread01 _th1;
public int foo = 0;
public Thread02(Thread01 th1){
_th1 = th1;
}
public void Run(){
try{
synchronized(_th1){_th1.wait();}
foo = _th1.foo;
for(int i=0;i<10;i++) foo += i;
synchronized(this){this.notify();};
}
catch(InterruptedException ie){ie.printStackTrace();}
}
}
public static void main(){
Thread01 th1 = new Thread01();
Thread02 th2 = new Thread02(th1);
th1.setThrd02(th2);
th1.start(); th2.start();
th1.join(); th2.join();
}
}
I think the assumption and corresponding purpose of the code is like
th2 run first, it is changed to waiting status by calling _th1.wait();
Then, th1 calculates foo and wake up th2, th1 goes into waiting status;
Th2 reads foo from thread1 and updated to 110, then wakes up th1 and th2 exit.
Then th1 exit.
The threads could be very risk because it is very possible that thread one runs first and thread 2 will wait forever.
I am not sure any other potential problems of the code.
One possible way that can fix the problem is, for example in the thread1
public class ThreadTest{
private static boolean updated = false;
private static boolean finished = false;
private static Thread01 extends Thread{
public void Run(){
// do calcuation
while(finished){
wait();
}
// output result
}
}
private static Thread02 extends Thread{
public void run(){
while(false){
wait();
}
foo = th1.foo;
// do calculation
// similar mechanism to notify thread 1
}
}
There is no guarantee of ordering in your threads. It's sufficient for Thread01 to go past
synchronized(this){this.notify();}; before Thread02 does synchronized(_th1){_th1.wait();} to have both threads waiting indefinitely.
Note: The fact that you are calling wait and notify on _th1 and _th2 is irrelevant. Threads here will be treated as any other object.
#Alex has already pointed out the problems with wait and notify not being called in the order the code expects them to be (+1). However, since this is an interview question there are several other things wrong with this code:
Horrible naming conventions and code formatting,
Public field accessors,
Synchronizing on a Thread object (bizarre),
Catching InterruptedException and then just exiting the Thread,
No exception handling,
(Personal preference) Not using the Java concurrency libraries.
I'm sure the question was posed to tie you in knots and figure out why the concurrency is broken but, IMHO, that code is so hideous i wouldn't even begin to debug it - i'd just throw it away.
Following can be a better fix
public class ThreadTest{
private static volatile boolean updated = false;
private static volatile boolean finished = false;
private static class Thread01 extends Thread{
private Thread02 _th2;
public int foo = 0;
public void setThread2(Thread02 th2){
_th2 = th2;
}
public void Run(){
for(int i=0;i<10;i++) foo += i;
System.out.print(" thread1 calcualtion " + foo + "\n");
try{
updated = true;
synchronized(this) {this.notify();};
synchronized(_th2){
while(!finished)
_th2.wait();
System.out.print("Foo: " + _th2.foo );
}
}
catch(InterruptedException ie){
ie.printStackTrace();
}
}
}
private static class Thread02 extends Thread{
private final Thread01 _th1;
public int foo = 0;
public Thread02(Thread01 th1){
_th1 = th1;
}
public void run(){
try{
synchronized(_th1){
while(!updated)
_th1.wait();
foo = _th1.foo;
}
for(int i=0;i<10;i++) foo +=i;
finished = true;
synchronized(this){ this.notify();}
}catch(InterruptedException ie){
ie.printStackTrace();
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread01 th1 = new Thread01();
Thread02 th2 = new Thread02(th1);
th1.setThread2(th2);
try{
th1.start();
th2.start();
th1.join();
th2.join();
}catch(InterruptedException ie){
ie.printStackTrace();
}
}
Related
Here is the code snippet:
public class PrintEvenOdd
public static class SynchronizedThreadMonitor {
public final static boolean ODD_TURN = true;
public final static boolean EVEN_TURN = false;
private boolean turn = ODD_TURN;
public synchronized void waitTurn(boolean oldTurn) {
while (turn != oldTurn) {
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException in wait(): " + e);
}
}
}
public synchronized void toggleTurn(){
turn ^= true;
notify();
}
}
public static class OddThread extends Thread {
private final SynchronizedThreadMonitor monitor;
public OddThread(SynchronizedThreadMonitor monitor) {
this.monitor = monitor;
}
#Override
public void run() {
for (int i=1; i<=100; i+=2) {
monitor.waitTurn(SynchronizedThreadMonitor.ODD_TURN);
System.out.println("i= " + i);
monitor.toggleTurn();
}
}
}
public static class EvenThread extends Thread {
private final SynchronizedThreadMonitor monitor;
public EvenThread(SynchronizedThreadMonitor monitor) {
this.monitor = monitor;
}
#Override
public void run() {
for (int i=2; i<=100; i+=2) {
monitor.waitTurn(SynchronizedThreadMonitor.EVEN_TURN);
System.out.println("i= " + i);
monitor.toggleTurn();
}
}
}
public static void main(String[] args) throws InterruptedException {
SynchronizedThreadMonitor monitor = new SynchronizedThreadMonitor();
Thread t1 = new OddThread(monitor);
Thread t2 = new EvenThread(monitor);
t1.start();
t2.start();
t1.join();
t2.join();
}
}
Using 2 threads to print numbers. One prints odd numbers and another prints even numbers.
In my understanding, both waitTurn and toggleTurn share the same LOCK of the instance. So if one holds the LOCK, the other method could not run. So if EvenThread first invokes waitTurn method and wait for the turn change, it holds the LOCK, then OddThread could not enter the toggleTurn method and set the turn. This should lead to a deadlock as per my understanding. But it did not happen.
Can someone please explain why the deadlock did not happen?
"So IF EvenThread first run waitTurn method and wait for the turn change, it holds the LOCK, the OddThread could NOT enter the toggleTurn method"
It holds the LOCK only small period of time, until method wait() is invoked. Method wait() releases the LOCK and allows another thread to enter the critical section.
I'm new to threads. I wanted to get two threads to increment an integer to a certain value. because int type is immutable, I switched to atomic integer. I also tried to wrap an int to a class and that didn't work either. I also tried static/volatile int and that didn't work. I also tried to use fairness policy. The main issue is that "counterObj" is not incremented correctly and is still set to 0 even though it is injected to both threads.
My expected running behavior:
thread value
thread 0 0
thread 1 1
thread 0 2
...
What I wrote so far:
import java.util.concurrent.atomic.AtomicInteger;
public class Application {
public static void main(String[] args) {
Application app = new Application();
try {
app.launch();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void launch() throws InterruptedException {
int increments = 100;
AtomicInteger counterObj = new AtomicInteger(0);
CounterThread th1 = new CounterThread("1", counterObj, increments);
CounterThread th2 = new CounterThread("2", counterObj, increments);
th1.start();
th2.start();
System.out.println(counterObj.get());
}
}
and
import java.util.concurrent.atomic.AtomicInteger;
public class CounterThread implements Runnable {
private final String threadID;
private AtomicInteger counterObj;
private int bound;
public CounterThread(String threadID, AtomicInteger counter, int bound) {
this.threadID = threadID;
this.counterObj = counter;
this.bound = bound;
}
#Override
public synchronized void run() {
while (counterObj.get() < bound) {
synchronized (this) {
counterObj.incrementAndGet();
}
}
System.out.println("Thread " + threadID + " finished");
}
public void start() throws InterruptedException {
Thread thread = new Thread(this, threadID);
thread.join();
thread.start();
}
}
Cheers!
I think your program is exiting before your threads get a chance to do anything (probably due to the ordering of your starts and joins. I would move your thread starting logic into your main(or launch) method. Something like the following.
Thread thread1 = new Thread(new MyCounterRunnable("1", counterObj, increments));
Thread thread2 = new Thread(new MyCounterRunnable("2", counterObj, increments));
Then, in your main, you need to call join after starting the threads...as follows:
thread1.start(); // starts first thread.
thread2.start(); // starts second thread.
thread1.join(); // don't let main exit until thread 1 is done.
thread2.join(); // don't let main exit until thread 2 is done.
What you really are wanting is for only one thread to increment an int at a time.
The int variable is the resource you want in the synchronized block, so the different threads can increment it one at a time.
This can be done using syncrhonize alone.
Disclaimer: I didn't run the code so it could have some typo or Exceptions to be removed from the Application class.
public class Application {
private int theVar = 0;
private int increments = 100;
public static void main(String[] args) {
Application app = new Application();
try {
app.launch();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized addOne(){
this.theVar++;
}
private void launch() throws InterruptedException {
Runnable counter1 = new Counter(this, increments), counter2 = new Counter(this, increments);
Thread t1 = new Thread(counter1);
Thread t2 = new Thread(counter2);
t1.start();
t2.start();
}
}
A counter class
public class Counter implements Runnable{
private Application app;
int rounds = -1;
public Counter(Application app, rounds){
this.app = app;
this.rounds = rounds;
}
public void run(){
while(int i=0; i<rounds; i++){
this.app.addOne();
}
}
}
AtomicInteger takes care of atomicity itself, so you shouldn't need to use synchronized -- but only if you play by the rules, and do your atomic operations in one call.
You're failing to do this, because you call counterObj.get() then depending on the result counterObj.incrementAndGet(). You need to avoid this because you want the check and the update to be part of the same atomic chunk of work.
You can get close with:
while(counterObj.incrementAndGet() < bound) {} ;
But this will always increment at least once, which may be once too many.
Slightly more involved:
IntUnaryOperator incrementWithLimit = x ->
( x < bound ? x + 1 : x );
while(counterObj.updateAndGet(incrementWithLimit) < bound) {};
That is, we've created a function that increments a number only if it's lower than bound, and we tell AtomicInteger to apply that.
There are a couple of issues with your code:
Thread.join method works only if the thread has started, else it does nothing. So you must reorder your code, but if you just move the join method after start, when starting the first thread by calling CounterThread.start, the main thread will wait until the started thread has finished, blocked in the Thread.join method, and only then will continue to starting the second one. A solution is to make an additional method in the CounterThread class, that will be called after both threads have been started:
public void waitFinish() throws InterruptedException {
thread.join();
}
synchronized (this) is synchronizing on the CounterThread instance that has been created when you called new CounterThread(...), but you have two instances so each will be synchronizing on a different object. For synchronized to work, you need to use a common instance of an object, in this case you can use the shared counterObj.
Only the AtomicInteger methods are guaranteed to be thread safe, so after you check if the bound has been reached outside the synchronized block, when entering the synchronized block the value can already be changed by another thread. So you need to do a recheck inside the synchronized block OR to first synchronize on the shared lock(counterObj) before the check and increment.
while (true) {
synchronized (counterObj) {
if (counterObj.get() < bound)
counterObj.incrementAndGet();
else break;
}
}
Note that the AtomicInteger class synchronized methods aren't helping now, but because it is a mutable object, it helps to use it as a shared lock. If you used an Integer instead, being immutable, a new instance will have been created when you incremented it. So now, it's only function is a wrapper holding the integer result.
Putting it all together:
public class Application {
public static void main(String[] args) {
Application app = new Application();
try {
app.launch();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void launch() throws InterruptedException {
int increments = 100;
AtomicInteger counterObj = new AtomicInteger(0);
CounterThread th1 = new CounterThread("1", counterObj, increments);
CounterThread th2 = new CounterThread("2", counterObj, increments);
th1.start();
th2.start();
th1.waitFinish();
th2.waitFinish();
System.out.println(counterObj.get());
}
}
public class CounterThread implements Runnable {
private final String threadID;
private AtomicInteger counterObj;
private int bound;
private Thread thread;
public CounterThread(String threadID, AtomicInteger counter, int bound) {
this.threadID = threadID;
this.counterObj = counter;
this.bound = bound;
}
#Override
public void run() {
while (true) {
synchronized (counterObj) {
if (counterObj.get() < bound)
counterObj.incrementAndGet();
else break;
}
}
System.out.println("Thread " + threadID + " finished");
}
public void start() throws InterruptedException {
thread = new Thread(this, threadID);
thread.start();
}
public void waitFinish() throws InterruptedException {
thread.join();
}
}
I've included a double check on the AtomicInteger, this appears to be what you've been trying to accomplish.
import java.util.concurrent.atomic.AtomicInteger;
public class DualCounters{
public static void main(String[] args) throws Exception{
AtomicInteger i = new AtomicInteger(0);
int bounds = 3;
Thread a = new Thread(()->{
int last = 0;
while(i.get()<bounds){
synchronized(i){
if(i.get()<bounds){
last = i.getAndIncrement();
}
}
}
System.out.println("a last " + last);
});
Thread b = new Thread(()->{
int last = 0;
while(i.get()<bounds){
synchronized(i){
if(i.get()<bounds){
last = i.getAndIncrement();
}
}
}
System.out.println("b last " + last);
});
a.start();
b.start();
a.join();
b.join();
System.out.println(i.get() + " afterwards");
}
}
The double check is a broken concept in java, the AtomicInteger offers tools for accomplishing this without any synchronization.
int a;
while((a = i.getAndIncrement())<bounds){
...
}
Now a will never be greater than bounds inside of the while loop. When the loop is finished i and a could have a value greater than bounds.
If that was an issue, there is always the other method getAndUpdate
while((a = i.getAndUpdate(i->i<bounds?i+1:i)<bounds){
...
}
I simply want to use thread to print out from 1 to 10. But my code will stop at number 1. input() will provide variable from 1 to 10, while output() will print out them. input() will be executed first and then output(). After that for() will make sure they will start another iteration.
class InputOutput{
private static int i=0;
private static boolean ToF=false;
synchronized void output(){
try{
while(!ToF){
notify();
wait();
}
}
catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Output: "+i);
ToF=false;
notify();
}
synchronized void input(){
try{
while(ToF){
notify();
wait();
}
}
catch(InterruptedException e){
e.printStackTrace();
}
i++;
ToF=true;
notify();
}
class input implements Runnable{
private int i=1;
InputOutput io=new InputOutput();
public void run(){
for(i=1;i<=10;i++)
io.input();
}
}
class output implements Runnable{
private int i=1;
InputOutput io=new InputOutput();
public void run(){
for(i=1;i<=10;i++)
io.output();
}
}
public class Homework07Part3 {
public static void main(String[] args) {
Thread t1=new Thread(new input());
t1.start();
Thread t2=new Thread(new output());
t2.start();
}
}
while loop you put wait on a single object for which two thread communication
while(ToF){
//dont put notify here.
notify();
wait();
}
Make it instance variable
private static boolean ToF=false;
public class Homework07Part3 {
public static void main(String[] args) {
InputOutput io = new InputOutput();
Thread t1 = new Thread(new input(io));
t1.start();
Thread t2 = new Thread(new output(io));
t2.start();
}
private static class input implements Runnable {
private int i = 1;
private InputOutput io;
public input(InputOutput io) {
this.io = io;
}
public void run() {
for (i = 1; i <= 10; i++)
io.input();
}
}
private static class output implements Runnable {
private int i = 1;
private InputOutput io;
public output(InputOutput io) {
this.io = io;
}
public void run() {
for (i = 1; i <= 10; i++)
io.output();
}
}
}
class InputOutput {
private int i = 0;
private boolean ToF = false;
synchronized void output() {
try {
while (!ToF) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Output: " + i);
ToF = false;
notify();
}
synchronized void input() {
try {
while (ToF) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
ToF = true;
notify();
}
}
I simply want to use thread to print out from 1 to 10. But my code will stop at number 1.
[[ The other answer seems to have fixed your problem but it doesn't explain what is happening and why the fix works. ]]
You problem is that both threads are calling synchronize and notify() and wait() on different objects. When threads communicate using these signals they both need to be sharing the same object instance. You are creating 2 InputOutput objects so both of your threads are stuck in wait() since the notify() calls are lost.
class Input implements Runnable{
...
// this is local to the Input class
InputOutput io=new InputOutput();
...
class Output implements Runnable{
...
// this is a different instance
InputOutput io=new InputOutput();
You should do something like the following:
final InputOutput io = new InputOutput();
Thread t1=new Thread(new Input(io));
t1.start();
Thread t2=new Thread(new Output());
t2.start();
...
private static class Input {
private final InputOutput io;
public Input(InputOutput io) { this.io = io; }
...
private static class Output {
private final InputOutput io;
public Output(InputOutput io) { this.io = io; }
...
So then both of your Input and Output classes are using the same instance of the InputOutput class. When they call synchronized on the methods, they are locking on the same instance and when they call wait() and notify() the signals are seen by the other thread.
I came across a Java problem about multi-threaded programming (please see the code below). Based on this question and answer on StackOverflow, I think I understand why there could be a deadlock. But what I don't understand was if the program works correctly (i.e. there is no deadlock), what would be the value of foo printed? I thought it would be 20 (thread1 counting up to 10 and thread2 counting up to 10 more). Could someone help me explain how this might (preferably in a simple way because I'm still new to thread programming)? Thank you.
public class ThreadTest{
private static class ThreadOne extends Thread{
private ThreadTwo threadTwo;
public int foo = 0;
public void setThreadTwo(ThreadTwo th){
threadTwo = th;
}
public void run(){
try{
for(int i=0;i<10;i++) foo += i;
synchronized(this){this.notify();};
synchronized(threadTwo){threadTwo.wait();};
System.out.print("Foo: " + threadTwo.foo);
}catch(InterruptedException e){ e.printStackTrace();}
}
}
private static class ThreadTwo extends Thread{
private final ThreadOne threadOne;
public int foo = 0;
public ThreadTwo(ThreadOne th){
threadOne = th;
}
public void Run(){
try{
synchronized(threadOne){threadOne.wait();}
foo = threadOne.foo;
for(int i=0;i<10;i++) foo += i;
synchronized(this){this.notify();};
}
catch(InterruptedException e){e.printStackTrace();}
}
}
public static void main(){
ThreadOne th1 = new ThreadOne();
ThreadTwo th2 = new ThreadTwo(th1);
th1.setThreadTwo(th2);
th1.start(); th2.start();
th1.join(); th2.join();
}
}
According to your code and without deadlocks foo value will be 90 (if i didn't miscalculate). Because instead of foo += 1 you did foo += i.
EDIT: Okay, step by step.
foo = 0
th1 and th2 starts. th2 waits for notify. th1 increments foo up to 45
th1 notifies and starts to wait th2. th2 is notified and starts to increment foo from 45 to 90
th2 notifies th1. th1 is notified, and it prints th2.foo, which is 90
EDIT 2: Correct way to count from 0 to 90 from 2 threads without concurrent modification is something like this
public class ThreadTest {
private static int counter = 0;
private static class Thread1 extends Thread {
final Object lock;
public Thread1(Object lock) {
this.lock = lock;
}
#Override
public void run() {
synchronized (lock) {
for (int i = 0; i < 10; i++)
counter += i;
}
}
}
private static class Thread2 extends Thread {
final Object lock;
public Thread2(Object lock) {
this.lock = lock;
}
#Override
public void run() {
synchronized (lock) {
for (int i = 0; i < 10; i++)
counter += i;
}
}
}
public static void main(String[] args) {
final Object lock = new Object();
final Thread th1 = new Thread1(lock);
final Thread th2 = new Thread2(lock);
th1.start();
th2.start();
try {
th1.join();
th2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Counter: " + counter);
}
}
But if you are forced to use wait and notify, than it's a bit more complicated. Use object of this class as common lock instead of Object
class Locker {
private boolean isLocked = false;
public synchronized void lock() throws InterruptedException {
while (isLocked) wait();
isLocked = true;
}
public synchronized void unlock() {
isLocked = false;
notify();
}
}
And in run method us it like this:
#Override
public void run() {
try {
locker.lock();
for (int i = 0; i < 10; i++)
counter += i;
locker.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Assume that one thread prints "Hello" and another prints "World". I have done it successfully for one time, as follows:
package threading;
public class InterThread {
public static void main(String[] args) {
MyThread mt=new MyThread();
mt.start();
synchronized(mt){
System.out.println("Hello");
try {
mt.wait();
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyThread extends Thread{
public void run(){
synchronized(this){
System.out.println("World!");
notify();
}
}
}
How do I do it for multiple time printing, say for 5 times? I tried putting for loop around the synchronized block, but of no use.
Here being two interdependent threads, we need two synchronizing objects. they could be one of many things. one integer, another object; one Boolean another object; both object; both semaphores and so on. the synchronization technique could be either Monitor or Semaphore any way you like, but they have to be two.
I have modified your code to use semaphore instead of Monitor. The Semaphore works more transparently. You can see the acquire and release happening. Monitors are even higher constructs. Hence Synchronized works under the hood.
If you are comfortable with the following code, then you can convert it to use Monitors instead.
import java.util.concurrent.Semaphore;
public class MainClass {
static Semaphore hello = new Semaphore(1);
static Semaphore world = new Semaphore(0);
public static void main(String[] args) throws InterruptedException {
MyThread mt=new MyThread();
mt.hello = hello;
mt.world = world;
mt.start();
for (int i=0; i<5; i++) {
hello.acquire(); //wait for it
System.out.println("Hello");
world.release(); //go say world
}
}
}
class MyThread extends Thread{
Semaphore hello, world;
public void run(){
try {
for(int i = 0; i<5; i++) {
world.acquire(); // wait-for it
System.out.println(" World!");
hello.release(); // go say hello
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadSeq {
Object hello = new Object();
Object world = new Object();
public static void main(String[] args) throws InterruptedException {
for(int i=0; i<6;i++){
Runnable helloTask = new Runnable(){
#Override
public void run(){
new ThreadSeq().printHello();
}
};
Runnable worldTask = new Runnable(){
#Override
public void run(){
new ThreadSeq().printWorld();
}
};
Thread t1 = new Thread(helloTask);
Thread t2 = new Thread(worldTask);
t1.start();
t1.join();
t2.start();
t2.join();
}
}
public void printHello(){
synchronized (hello) {
System.out.println("Hello");
}
}
public void printWorld(){
synchronized (world) {
System.out.println("World");
}
}
}
The goal here is to synchronize threads so that when one is done it notify the other. If I have to make it, it would be 2 threads executing the same code with different data. Each thread has its own data ("Hello" and true to T1, "World" and false to t2), and share a variable turn plus a separate lock object.
while(/* I need to play*/){
synchronized(lock){
if(turn == myturn){
System.out.println(mymessage);
turn = !turn; //switch turns
lock.signal();
}
else{
lock.wait();
}
}
}
Before you start trying to get it to work five times you need to make sure it works once!
Your code is not guaranteed to always print Hello World! - the main thread could be interrupted before taking the lock of mt (note that locking on thread objects is generally not a good idea).
MyThread mt=new MyThread();
mt.start();
\\ interrupted here
synchronized(mt){
...
One approach, that will generalise to doing this many times, is to use an atomic boolean
import java.util.concurrent.atomic.AtomicBoolean;
public class InterThread {
public static void main(String[] args) {
int sayThisManyTimes = 5;
AtomicBoolean saidHello = new AtomicBoolean(false);
MyThread mt=new MyThread(sayThisManyTimes,saidHello);
mt.start();
for(int i=0;i<sayThisManyTimes;i++){
while(saidHello.get()){} // spin doing nothing!
System.out.println("Hello ");
saidHello.set(true);
}
}
}
class MyThread extends Thread{
private final int sayThisManyTimes;
private final AtomicBoolean saidHello;
public MyThread(int say, AtomicBoolean said){
super("MyThread");
sayThisManyTimes = say;
saidHello = said;
}
public void run(){
for(int i=0;i<sayThisManyTimes;i++){
while(!saidHello.get()){} // spin doing nothing!
System.out.println("World!");
saidHello.set(false);
}
}
}
This is in C:
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t hello_lock, world_lock;
void printhello()
{
while(1) {
pthread_mutex_lock(&hello_lock);
printf("Hello ");
pthread_mutex_unlock(&world_lock);
}
}
void printworld()
{
while(1) {
pthread_mutex_lock(&world_lock);
printf("World ");
pthread_mutex_unlock(&hello_lock);
}
}
int main()
{
pthread_t helloThread, worldThread;
pthread_create(&helloThread,NULL,(void *)printhello,NULL);
pthread_create(&helloThread,NULL,(void *)printhello,NULL);
pthread_join(helloThread);
pthread_join(worldThread);
return 0;
}
There are two thread and both has its own data ("Hello" and true to ht, "World" and false to wt), and share a variable objturn.
public class HelloWorldBy2Thread {
public static void main(String[] args) {
PrintHelloWorld hw = new PrintHelloWorld();
HelloThread ht = new HelloThread(hw);
WorldThread wt = new WorldThread(hw);
ht.start();
wt.start();
}
}
public class HelloThread extends Thread {
private PrintHelloWorld phw;
private String hello;
public HelloThread(PrintHelloWorld hw) {
phw = hw;
hello = "Hello";
}
#Override
public void run(){
for(int i=0;i<10;i++)
phw.print(hello,true);
}
}
public class WorldThread extends Thread {
private PrintHelloWorld phw;
private String world;
public WorldThread(PrintHelloWorld hw) {
phw = hw;
world = "World";
}
#Override
public void run(){
for(int i=0;i<10;i++)
phw.print(world,false);
}
}
public class PrintHelloWorld {
private boolean objturn=true;
public synchronized void print(String str, boolean thturn){
while(objturn != thturn){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(str+" ");
objturn = ! thturn;
notify();
}
}
In simple way we can do this using wait() and notify() without creating any extra object.
public class MainHelloWorldThread {
public static void main(String[] args) {
HelloWorld helloWorld = new HelloWorld();
Thread t1 = new Thread(() -> {
try {
helloWorld.printHello();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
helloWorld.printWorld();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// printHello() will be called first
t1.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
}
}
class HelloWorld {
public void printHello() throws InterruptedException {
synchronized (this) {
// Infinite loop
while (true) {
// Sleep for 500ms
Thread.sleep(500);
System.out.print("Hello ");
wait();
// This thread will wait to call notify() from printWorld()
notify();
// This notify() will release lock on printWorld() thread
}
}
}
public void printWorld() throws InterruptedException {
synchronized (this) {
// Infinite loop
while (true) {
// Sleep for 100ms
Thread.sleep(100);
System.out.println("World");
notify();
// This notify() will release lock on printHello() thread
wait();
// This thread will wait to call notify() from printHello()
}
}
}
}