OK, So I have these classes that extend Thread, what I'm supposed to do is:
Let all alumns arrive.
When alumns arrive they say 'Hi'.
If the teacher arrives but not all of the Alumns have arrived then he should wait() for them.
Alumns should notify() the teacher when they're all there.
An alumn is a Thread initialized with boolean value 0.
A teacher is a Thread initialized with boolean value 1.
Person/Greeting Code
public class Person extends Thread {
private Thread t;
private String threadName;
boolean id;
Greeting greeting;
public Person(String name,boolean tipo,int n){
this.threadName = name;
this.id=tipo;
greeting =new Greeting();
}
#Override
public void run() {
if(id==false) {
try {
greeting.alumn(threadName);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
else{
try {
greeting.teacher(threadName);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
public void start()
{
System.out.println("Starting "+ threadName);
if(t==null)
{
t=new Thread(this,threadName);
t.start();
}
}
}
class Greeting {
public void alumn(String s) throws InterruptedException{
System.out.println(s);
synchronized (this){
System.out.println("Alumn: "+s);
notifyAll();
}
}
public synchronized void teacher(String s) throws InterruptedException {
wait();
System.out.println(s);
}
}
Main class
public class ClassRoom {
public static void main(String [] args) {
Person francisco = new Person("Francisco",false,1);
Person jesus = new Person("Jesus", false,2);
Person alberto = new Person("Alberto",false,3);
Person karla = new Person("Karla",false,4);
Person maestro = new Person("Professor",true,0);
francisco.start();
jesus.start();
alberto.start();
karla.start();
maestro.start();
}
}
The problem:
If the teacher arrives first he goes to wait()...then alumns arrive but he never wakes up.
If the teacher doesn't arrive first, he still never wakes up!
How to fix this?
If the teacher arrives first he goes to wait()...then alumns arrive
but he never wakes up.
All you Persons instantiate their own Greeting, which synchronzizes on this and therefore also waits/notifies on this. Each Person uses its own semaphore, which is not what you want. You should synchronize on the same object (perhaps Greeting.class) for all instances.
If the teacher doesn't arrive first, he still never wakes up! How to fix this?
Simply check if all alumns are there. If yes greet, else wait for notify. Afterwards check again. The check has to be part of the synchronized block to avoid race conditions.
To wait until all threads has arrived to certain point, consider using CyclicBarrier.
Related
This contrived project will eventually deadlock, won't it?
Two methods are synchronized in a shared object. The two threads will eventually find themselves in one of those methods and trying to invoke the other method. I think.
package main;
import java.util.ArrayList;
import java.util.List;
import myThread.MyThread;
import sharedObject.SharedObject;
import uncooperativeThread.UncooperativeThread;
public class Main {
public static void main(String[] args) {
competingThreads();
//uncooperativeThreads();
}
private static void competingThreads() {
List<MyThread> myThreads = new ArrayList<MyThread>();
SharedObject sharedObject = new SharedObject();
int threads = 2;
for (int i = 0; i < threads; i++) {
myThreads.add(new MyThread(i, sharedObject));
}
for (MyThread t : myThreads) {
t.start();
}
for (MyThread t : myThreads) {
try {t.join();} catch (Exception ex) {}
}
}
/**
* We will try to call SharedObject.methodC from two threads. The first one will get in, the second will have to wait.
*/
private static void uncooperativeThreads() {
SharedObject sharedObject = new SharedObject();
UncooperativeThread t1 = new UncooperativeThread(1, sharedObject);
UncooperativeThread t2 = new UncooperativeThread(2, sharedObject);
t1.start();
t2.start();
try {t1.join();} catch (Exception ex) {}
try {t2.join();} catch (Exception ex) {}
}
}
package myThread;
import sharedObject.SharedObject;
public class MyThread extends Thread {
private int id;
SharedObject sharedObject;
public MyThread(int id, SharedObject sharedObject) {
this.id = id;
this.sharedObject = sharedObject; // Reference
}
public void run() {
doStuff();
}
private void doStuff() {
int counter = 0;
while (true) {
System.out.println(++counter);
if (id % 2 == 1) {
sharedObject.methodA(id);
} else {
sharedObject.methodB(id);
}
}
}
}
package sharedObject;
import java.util.Random;
public class SharedObject {
public synchronized void methodA(int id) {
//System.out.println("methodA(): Thread " + id);
try {Thread.sleep((new Random()).nextInt(1000));} catch(Exception ex) {}
if (id == 0) {return;}
// What I want is for one thread to try to call methodB() while the *other* thread is in methodB() trying to call methodA().
methodB(id);
}
public synchronized void methodB(int id) {
//System.out.println("methodB(): Thread " + id);
try {Thread.sleep((new Random()).nextInt(1000));} catch(Exception ex) {}
if (id == 1) {return;}
methodA(id);
}
}
// What I want is for one thread to try to call methodB() while the other thread is in methodB() trying to call methodA().
That's not a deadlock. The thread that's trying to call methodB() simply will be forced to wait until the other thread releases the lock by returning from its methodB() call.
To get a classic deadlock, you need to have two locks. Your program has only one lockāthe intrinsic lock belonging to the single instance of SharedObject that your program creates.
A classic deadlock is when one thread has already acquired lock A and is waiting to acquire lock B while the other thread has acquired lock B, and it's waiting to acquire lock A. In that case, neither thread can make progress until the other thread releases its lock. But, neither thread will release its lock because neither thread can make progress.
You need two locks. You have two methods (methodA() and methodB()), but they both lock the same lock.
I would like to say that I tried to find some answers on this site but I couldn't manage, also this is my first question so I am sorry if i wrote it off format etc...
I am trying to learn java and now trying to understand thread section. So far I understood some basics and I wanted to try this: a lieutenant class shares the monitor-lock with a soldier class but I am failing at somewhere.
Edit: I want to Lieutenant waits until the Soldier says his first line, then he gives an order. But when soldier tries to release lock I get an monitor error because of notify method.
"Exception in thread "Thread-1" java.lang.IllegalMonitorStateException."
P.S: I know there are easier ways but I am trying to utilize wait¬ify.
public class Lieutenant {
private boolean waitForCommand = true;
public void setWaitForCommand(boolean waitForCommand) {
this.waitForCommand = waitForCommand;
}
public synchronized void giveOrder() {
while (waitForCommand) {
try {
wait();
} catch (InterruptedException e) {
e.getStackTrace();
}
System.out.println("I said run soldier! RUN!");
}}}
public class Soldier {
private final Lieutenant lieutenant;
public Soldier(Lieutenant lieutenant) {
this.lieutenant = lieutenant;
}
public void getOrder() {
synchronized (this.lieutenant) {
System.out.println("Sir! Yes, sir!");
lieutenant.setWaitForCommand(false);
notifyAll();
}}}
class Main {
public static void main(String[] args) {
Lieutenant lieutenant = new Lieutenant();
Soldier soldier = new Soldier(lieutenant);
new Thread(new Runnable() {
#Override
public void run() {
lieutenant.giveOrder();
}}).start();
new Thread(new Runnable() {
#Override
public void run() {
soldier.getOrder();
}}).start();
}}
The immediate problem here is with this method:
synchronized (this.lieutenant) {
System.out.println("Sir! Yes, sir!");
lieutenant.setWaitForCommand(false);
notifyAll();
}}
The synchronized block is holding a lock on this.lieutenant but you are attempting to call notifyAll() on this, which you aren't holding the lock on.
If make this change
synchronized (this.lieutenant) {
System.out.println("Sir! Yes, sir!");
lieutenant.setWaitForCommand(false);
this.lieutenant.notifyAll();
}}
It should work better. But as mentioned in the comments you can't guarantee that giveOrder will be called before getOrder.
So my task is this:
Instantiate two object of the same class
Provide a constructor argument, to designate a thread as even and another as odd .
Start both threads right one after other
Odd thread prints odd numbers from 0 to 1000
Even thread prints even numbers from 0 to 1000
However they should be in sync the prints should be 1 , 2 , 3 , 4 .....
One number on each line
However I can't seem to get the locks to release correctly. I've tried reading some of the similar problems on here but they all use multiple classes. What am I doing wrong?
Edit: My main class is doing this -
NumberPrinter oddPrinter = new NumberPrinter("odd");
NumberPrinter evenPrinter = new NumberPrinter("even");
oddPrinter.start();
evenPrinter.start();
and my output is -
odd: 1
even: 2
...
public class NumberPrinter extends Thread {
private String name;
private int starterInt;
private boolean toggle;
public NumberPrinter(String name) {
super.setName(name);
this.name=name;
if(name.equals("odd")) {
starterInt=1;
toggle = true;
}
else if(name.equals("even")) {
starterInt=2;
toggle = false;
}
}
#Override
public synchronized void run() {
int localInt = starterInt;
boolean localToggle = toggle;
if(name.equals("odd")) {
while(localInt<1000) {
while(localToggle == false)
try {
wait();
}catch(InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println(name+": "+localInt);
localInt +=2;
localToggle = false;
notify();
}
}
else {
while(localInt<1000) {
while(localToggle == true)
try {
wait();
}catch(InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println(name+": "+localInt);
localInt +=2;
localToggle = true;
notify();
}
}
}
}
The key problem here is that the two threads have no way to coordinate with each other. When you have a local variable (localToggle in this case) nothing outside the method can observe or alter its value.
If you share one object with both threads, however, its state can change, and if used correctly, those state changes will be visible to both threads.
You will see examples where the shared object is an AtomicInteger, but when you use synchronized, wait() and notify(), you don't need the extra concurrency overhead built into the atomic wrappers.
Here's a simple outline:
class Main {
public static main(String... args) {
Main state = new Main();
new Thread(new Counter(state, false)).start();
new Thread(new Counter(state, true)).start();
}
int counter;
private static class Counter implements Runnable {
private final Main state;
private final boolean even;
Counter(Main state, boolean even) {
this.state = state;
this.even = even;
}
#Override
public void run() {
synchronized(state) {
/* Here, use wait and notify to read and update state.counter
* appropriately according to the "even" flag.
*/
}
}
}
}
I'm not clear whether using wait() and notify() yourself is part of the assignment, but an alternative to this outline would be to use something like a BlockingQueue to pass a token back and forth between the two threads. The (error-prone) condition monitoring would be built into the queue, cleaning up your code and making mistakes less likely.
I finally got it working in a way that meets the standards required by my assignment.
Thank you all for your input. I'll leave the answer here for anyone who might need it.
public class Demo {
public static void main(String[] args) {
NumberPrinter oddPrinter = new NumberPrinter("odd");
NumberPrinter evenPrinter = new NumberPrinter("even");
oddPrinter.start();
evenPrinter.start();
System.out.println("Calling thread Done");
}
public class NumberPrinter extends Thread {
private int max = 1000;
static Object lock = new Object();
String name;
int remainder;
static int startNumber=1;
public NumberPrinter(String name) {
this.name = name;
if(name.equals("even")) {
remainder=0;
}else {
remainder=1;
}
}
#Override
public void run() {
while(startNumber<max) {
synchronized(lock) {
while(startNumber%2 !=remainder) {
try {
lock.wait();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name+": "+startNumber);
startNumber++;
lock.notifyAll();
}
}
}
}
I have two synchronized methods and I'm using the mediator design pattern.
I'm trying to avoid deadlocks, which is (from what I understand) for example when a thread has a lock on a variable res1 but needs a lock on variable res2. The other thread needs the lock for res1 but has the lock for res2 - resulting in a deadlock, right?
Assuming my understanding of deadlocks are correct, then my question is whether or not I have solved the issue of deadlock in this code?
I have two synchronized methods and two threads.
public class Producer extends Thread {
private Mediator med;
private int id;
private static int count = 1;
public Producer(Mediator m) {
med = m;
id = count++;
}
public void run() {
int num;
while(true) {
num = (int)(Math.random()*100);
med.storeMessage(num);
System.out.println("P-" + id + ": " + num);
}
}
}
public class Consumer extends Thread {
private Mediator med;
private int id;
private static int count = 1;
// laver kopling over til mediator
public Consumer(Mediator m) {
med = m;
id = count++;
}
public void run() {
int num;
while(true) {
num = med.retrieveMessage();
System.out.println("C" + id + ": " + num);
}
}
}
public class Mediator {
private int number;
private boolean slotFull = false;
public synchronized void storeMessage(int num) {
while(slotFull == true) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
slotFull = true;
number = num;
notifyAll();
}
public synchronized int retrieveMessage() {
while(slotFull == false) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
slotFull = false;
notifyAll();
return number;
}
}
public class MediatorTest {
public static void main(String[] args) {
Mediator mb = new Mediator();
new Producer(mb).start();
new Producer(mb).start();
new Producer(mb).start();
new Consumer(mb).start();
new Consumer(mb).start();
}
}
for example when a thread has a lock on a variable res1 but needs a lock on variable res2
What matters is not that there are two variables, what matters is that there must be two (or more) locks.
The names "res1" and "res2" are meant to suggest two resources each of which may have one or more variables, and each of which has its own lock. Here's where you get into trouble:
final Object lock1 = new Object();
final Object lock2 = new Object();
public void method1() {
synchronized (lock1) {
// Call Thread.sleep(1000) here to simulate the thread losing its time slice.
synchronized(lock2) {
doSomethingThatRequiresBothLocks
}
}
}
public void method2() {
synchronized (lock2) {
// Do the same here 'cause you can't know which thread will get to run first.
synchronized(lock1) {
doSomethingElseThatRequiresBothLocks()
}
}
}
If thread A calls method1(), there is a very small chance that it could lose its time slice (i.e., turn to run) just after it successfully locks lock1, but before it locks lock2.
Then, while thread A is waiting its turn to run again, thread B calls method2(). Thread B will be able to lock lock2, but then it gets stuck because lock1 is locked by thread A. Furthermore, when thread A gets to run again, it will immediately be blocked when it tries to lock lock2 which is owned by thread B. Neither thread will ever be able to continue from that point.
In real code, it's never so obvious. When it happens in real-life, it usually is because of some unforseen interaction between code from two or more different modules that may not even be aware of each other, but which access the same common resources.
Your understanding of the basic deadlock problem is correct. With your second question about validity of your solution to the deadlock problem, you've only got 1 lock, so I'd say "yes" by default, since the deadlock you described isn't possible in this situation
I agree with what #ControlAltDel has said. And your understanding of a deadlock matches mine. Whereas there are a few different ways in which a deadlock can manifest itself, the way you describe -- inconsistently acquiring multiple monitors by involved threads (methods) causes deadlock.
Another way would be to (for example,) sleep while holding a lock. As you coded correctly, when the producer finds that slotFull = true, it waits, giving up the lock, so the other thread (consumer, which is sharing the same instance of Mediator with producer) can make progress potentially causing this thread also to make progress after it gets a notification. If you had chosen to call Thread.sleep() instead (naively hoping that someone will cause the sleep to end when the condition would be false), then it would cause a deadlock because this thread is sleeping, still holding the lock, denying access to the other thread.
Every object has one lock which restrict multiple threads to access same block of code or method when you use synchronized keyword.
Coming to your problem, it will not deadlock.
If you have two independent attribute in a class shared by multiple threads, you must synchronized the access to each variable, but there is no problem if one thread is accessing one of the attribute and another thread accessing the other at the same time.
class Cinema {
private long vacanciesCinema1; private long vacanciesCinema2;
private final Object controlCinema1, controlCinema2;
public Cinema() {
controlCinema1 = new Object();
controlCinema2 = new Object();
vacanciesCinema1 = 20;
vacanciesCinema2 = 20;
}
public boolean sellTickets1(int number) {
synchronized (controlCinema1) {
if (number < vacanciesCinema1) {
vacanciesCinema1 -= number;
return true;
} else {
return false;
}
}
}
public boolean sellTickets2(int number) {
synchronized (controlCinema2) {
if (number < vacanciesCinema2) {
vacanciesCinema2 -= number;
return true;
} else {
return false;
}
}
}
public boolean returnTickets1(int number) {
synchronized (controlCinema1) {
vacanciesCinema1 += number;
return true;
}
}
public boolean returnTickets2(int number) {
synchronized (controlCinema2) {
vacanciesCinema2 += number;
return true;
}
}
public long getVacanciesCinema1() {
return vacanciesCinema1;
}
public long getVacanciesCinema2() {
return vacanciesCinema2;
}
}
class TicketOffice1 implements Runnable {
private final Cinema cinema;
public TicketOffice1(Cinema cinema) {
this.cinema = cinema;
}
#Override
public void run() {
cinema.sellTickets1(3);
cinema.sellTickets1(2);
cinema.sellTickets2(2);
cinema.returnTickets1(3);
cinema.sellTickets1(5);
cinema.sellTickets2(2);
cinema.sellTickets2(2);
cinema.sellTickets2(2);
}
}
public class CinemaMain {
public static void main(String[] args) {
Cinema cinema = new Cinema();
TicketOffice1 ticketOffice1 = new TicketOffice1(cinema);
Thread thread1 = new Thread(ticketOffice1, "TicketOffice1");
TicketOffice2 ticketOffice2 = new TicketOffice2(cinema);
Thread thread2 = new Thread(ticketOffice2, "TicketOffice2");
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("Room 1 Vacancies: %d\n", cinema.getVacanciesCinema1());
System.out.printf("Room 2 Vacancies: %d\n", cinema.getVacanciesCinema2());
}
}
I'm writing a small program to help me learn some multithreading in java, and I'm stuck on how to implement some scenario.
The program simulates a gas station that also has a coffee house in it.
I want to be able to create the following scenario:
add a person to a gas pump queue.
at the same time add a person to a cashier queue in the coffee house.
if the person's turn in the pump queue arrives before the turn in the cashier queue, allow him to choose what to do (stay in cashier queue and quit the pump queue or the other way around).
How can I jump between these 2 states?
So far I have this:
The Person class
public class Person implements Runnable {
private GasPump pump;
private Cashier cashier;
...
public void pumpGas() throws InterruptedException {
synchronized (this) {
pump.addCarToQueue(this);
wait();
}
synchronized (pump) {
sleep((long) (Math.random() * 5000));
pump.notify();
}
}
public void buyCoffee() throws InterruptedException {
synchronized (this) {
cashier.addCustomerToQueue(this); // standing inline
wait();
}
synchronized (cashier) {
sleep((long) (Math.random() * 5000)); // paying at cashier
cashier.notify();
}
}
...
}
The GasPump class
public class GasPump implements Runnable {
private Queue<Person> cars;
...
#Override
public void run() {
while (gasStation.isOpen()) {
if (!cars.isEmpty()) {
Car firstCar = cars.poll();
if (firstCar != null) {
synchronized (firstCar) {
firstCar.notifyAll();
}
} else {
// ?
}
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
...
}
And the Cashier class
public class Cashier implements Runnable {
private Queue<Person> customers;
...
#Override
public void run() {
while(coffeeHouse.isOpen()){
if(!customers.isEmpty()){
Car firstCustomer = customers.poll();
if(firstCustomer != null){
synchronized (firstCustomer) {
firstCustomer.notifyAll();
}
}
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
...
}
You should avoid using wait and notify as it is difficult to use them correctly and efficiently - use the classes from java.util.concurrent instead.
What I would do: add two boolean flags to your Person: hasPumped and hasShopped - once a person pumps their gas or shops then you set the appropriate flag to true.
Replace your Queues with BlockingQueues (probably the LinkedBlockingQueue is appropriate here) - this is a thread-safe queue, and you can call take on it in order to block until the queue is non-empty (rather than polling and then sleeping if the queue is empty). If you prefer to poll and sleep then you may want to use a ConcurrentLinkedQueue instead, though I advise that you use take on a BlockingQueue instead.
Add a Person to the GasPump and Cashier queues. When the person is removed from the queue via take or poll, then check its hasPumped or hasShopped flag to determine if any additional action is needed, for example if the Cashier takes the person and hasPumped is true then there's no need to ask the Person if they want to continue waiting in the gas queue since they've already finished pumping.
If the person chooses to quit a queue, then call remove(person) on the appropriate queue.
When the person finishes pumping gas then put them in the cashier queue if their hasShopped flag is false, and likewise put them in the gas queue when they've finished shopping if their hasPumped flag is false.
You shouldn't need any synchronized blocks or methods with this implementation.
public class Person implements Runnable {
private GasPump pump;
private Cashier cashier;
private boolean hasPumped, hasShopped, readyToPump, readyToShop;
private Thread thread;
public void run() {
thread = Thread.getCurrentThread();
while(!hasPumped && !hasShopped) {
try {
readyToPump = false;
readyToShop = false;
if (!hasPumped)
pumpGas();
if(!hasShopped)
buyCoffee();
thread.sleep(FOREVER);
} catch (InterruptedException ex) {
// check flags to see what to do next
}
}
}
public void pumpGas() {
pump.addCarToQueue(this);
}
public void buyCoffee() {
cashier.addCustomerToQueue(this);
}
public void setReadyToPump() {
readyToPump = true;
thread.interrupt();
}
public void setReadyToShop() {
readyToShop = true;
thread.interrupt();
}
}
public class GasPump implements Runnable {
private BlockingQueue<Person> cars = new LinkedBlockingQueue<>();
#Override
public void run() {
while (gasStation.isOpen()) {
Person person = cars.take();
person.setReadyToPump();
}
// clean up persons in queue
}
}
public class Cashier implements Runnable {
private BlockingQueue<Person> customers = new LinkedBlockingQueue();
#Override
public void run() {
while(coffeeHouse.isOpen()){
Person person = customers.take();
person.setReadyToShop();
}
// clean up persons in queue
}
}