I'm working on a school assignment where I'm supposed to synchronize two threads using monitors. In this case each monitor controls the access of a piece of railway and the trains need to lock that piece of railway so that the other one can't access it or has to wait until that piece of track is free. I have never used monitors before, so I'm sure it's my limited knowledge of how monitors work that is the problem. The trains and their threads themselves work perfectly, I've successfully used binary semaphores in the same code. Now I'm trying to replace the semaphores with monitors.
I basically wonder how conditions and locks works exactly. I've read on different blogs and forums but can't seem to grasp the concept.
Important note: I'm not allowed to use the synchronized keyword.
When I run the current code, i get the following error. The error occurs at occupied.signal() in the leave method:
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signalAll(AbstractQueuedSynchronizer.java:1956)
This is the code so far:
public class Monitor {
private final Lock lock = new ReentrantLock();
private final Condition occupied = lock.newCondition();
private boolean isOccupied = false;
private int id;
public Monitor(int id) {
super();
this.id = id;
}
public void enter(){
lock.lock();
try {
if(isOccupied)
occupied.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
isOccupied = true;
}
public boolean tryEnter(){
if(isOccupied){
return false;
}else{
enter();
return true;
}
}
public void leave(){
lock.unlock();
isOccupied = false;
occupied.signal();
}
}
I would greatly appreciate any help and/or ideas of what is wrong.
Thanks!
Your locking is too coarse. As a general pattern, unless you have very exceptional circumstances, all locking should be of the form:
lock.lock();
try {
....
} finally {
lock.unlock();
}
You are not using this pattern (locking and unlocking in different methods even).
Technically, your problem is that you are signalling the occupied condition when you are not holding the lock monitor.
In your program, the 'exclusive' lock on your track section is not supposed to be the actual Java Lock mechanism, but the boolean variable isOccupied. Change your code so that the two methods do a correct try...finally block, and also, you should possibly rename your Condition to be 'unoccupied', and reverse the logic of holding it.
public void enter(){
lock.lock();
try {
while(isOccupied)
unoccupied.await();
isOccupied = true;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void leave(){
lock.lock();
try {
isOccupied = false;
unoccupied.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
You don't have to implement your own monitor. Lock is Monitor:
public class Monitor {
private final Lock lock = new ReentrantLock();
private int id;
public Monitor(int id) {
super();
this.id = id;
}
public void enter(){
lock.lock();
}
public boolean tryEnter(){
return lock.tryLock();
}
public void leave(){
lock.unlock();
}
}
Related
I'm learning concurrency and I'm not quite certain as to why the output changes when I move the printSuccess function outside the synchronized block
Ive read the Oracle concurrency documentation and enough SO threads to understand the basic concepts and functionality at play. However, I can't explain this effect.
class ThreadTesting extends Thread {
volatile static int turn = 1;
public int id;
private static final Logger LOGGER = Logger.getLogger(ThreadTesting.class.getName());
public ThreadTesting(int id) {
this.id = id;
}
public void run() {
synchronized(this) {
if(id != turn) {
try {
wait();
} catch (InterruptedException e) {
LOGGER.info("Interrupted: " + id);
}
}
printSuccess(id);
}
}
public void printSuccess(int id) {
turn++;
System.out.println("Done:" + id);
notifyAll();
}
I'm initiallizing a set of the above objects (with ids 1-n) and calling .start() on each. I expect that they would all print out their id's in order. However the result changes unexpectedly if I move the printSuccess() function outside the synchronized block.
Thank you in advance.
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 have a Thread and I need to set when it is listening or in standby, for that I've defined
public static enum ListenerState { STAND_BY, LISTENING };
and a method
public void setState(ListenerState state){
this.state = state;
}
now, in the main loop I check the state in this way
#Override
public void run() {
while (!Thread.interrupted()) {
try {
if (state==ListenerState.LISTENING){
// do my job
}
else{
Thread.sleep(300);
}
}
}
}
Is this approach thread-safe ?
No, do like that:
class MyThread implements Runnable {
private volatile ListenerState state;
public synchronized void setState(ListenerState state){
this.state = state;
}
#Override
public void run() {
while (true) {
try {
if (state==ListenerState.LISTENING){
// do my job
} else{
Thread.sleep(300);
}
} catch (IterruptedException ex){
return;
}
}
}
}
You can find your answer here: Do I need to add some locks or synchronization if there is only one thread writing and several threads reading?
in one word: better to add volatile keyword to state.
if state can be changed or read by different thread, then you need to synronize block for reading and writing methods. or as a better way, use AtomicBoolean. it is perfect object to get rid of syncronize block and make it thread safe
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html
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.