using semaphores to synchronize threads in java

Hi,
      I have a very simple application (see attached file) which is supposed to alternatively print  to screen;
TA going first!
TB going second!
TA going first!
TB going second!

until the process is interrupted....
i'm using 2 threads and a semaphore to synchronize thread execution, however when i put a for loop in main to show  the output as above, the output is not consistently alternating between statements as i expected.
When i comment out  the loop (currently commented out) the statements alternate as expected.
can someone have a look at  my code and see if they can highlight   the problem? Or have i misunderstood semaphores entirely?
thanks


semaphoreEx1.java
blossomparkAsked:
Who is Participating?
 
mnrzCommented:
sorry I forgot to put finally block

and please note that this is not guaranteed that the TA is executing first but the order will be guaranteed. if you want the TA always runs first you need to put a delay between TA start() method and TB start() method

import java.util.concurrent.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class SemaphoreEx2{
	public static void main(String args[]){
		Lock lock = new ReentrantLock();
		Condition mineA = lock.newCondition();
		Condition mineB = lock.newCondition();
		
		new TA(lock,mineA,mineB).start();
		new TB(lock,mineA,mineB).start();
		
	}
}

class TA extends Thread{
	Lock lock ;
	Condition mineA;
	Condition mineB;
	public TA(Lock lock, Condition mineA,Condition mineB) {
		this.lock = lock;
		this.mineA = mineA;
		this.mineB = mineB;
	}
	public void run(){
		for (int i=0;i<10;i++){
		//put code for TA here
		try{
			lock.lock();
			System.out.println("TA going first!");
			mineB.signal();
			mineA.await();
		}catch(InterruptedException e){}
		finally{
			lock.unlock();
		}
		}
	}
}
class TB extends Thread {
	Lock lock ;
	Condition mineA;
	Condition mineB;
	public TB(Lock lock, Condition mineA,Condition mineB) {
		this.lock = lock;
		this.mineA = mineA;
		this.mineB = mineB;
	}
	public void run(){
		for (int i=0;i<10;i++){
			try{
				lock.lock();
				System.out.println("TB going second!");
				mineA.signal();
				mineB.await();
			}catch(InterruptedException e){}
			finally{
				lock.unlock();
			}
			
		}
	}
} 
	

Open in new window

0
 
mnrzCommented:
The code works fine for me! However I think you should remove the for-loop and put a while() in each thread
0
 
mnrzCommented:
This is the result. Id this what you expect?

TA going first!
TB going second!
TA going first!
TB going second!
TA going first!
TB going second!
TA going first!
TB going second!
TA going first!
TB going second!
TA going first!
TB going second!
TA going first!
TB going second!
TA going first!
TB going second!
TA going first!
TB going second!
TA going first!
TB going second!


0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

 
blossomparkAuthor Commented:
hi mnrz,
no..i'm getting random results like;
TA going first!
TA going first!
TA going first!
TB going second!
TB going second!
TA going first!
TA going first!
TB going second!
TA going first!
TB going second!
TA going first!
TB going second!
TA going first!
TB going second!
TA going first!
TA going first!
TB going second!
TB going second!
TB going second!
TB going second!

Process completed.
0
 
blossomparkAuthor Commented:
ps ...why get rid of  the for loop?
0
 
mnrzCommented:
Yes you get that result because each time you call start() method the order you run is not guaranteed to be executed as expected that is why I told you put a while in each thread and remove the for-loop from that main method
0
 
blossomparkAuthor Commented:
is that how you got  the correct output..using while loops in  the threads?
0
 
blossomparkAuthor Commented:
do you mean put a while loop in the run method of each thread?
0
 
mnrzCommented:
the result I got was actually by chance

check this code:


import java.util.concurrent.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class SemaphoreEx2{
	public static void main(String args[]){
		Lock lock = new ReentrantLock();
		Condition mineA = lock.newCondition();
		Condition mineB = lock.newCondition();
		
	//for (int i=0;i<10;i++){
		new TA(lock,mineA,mineB).start();
		new TB(lock,mineA,mineB).start();
	//		} 
		
	}
}
class TA extends Thread{
	Lock lock ;
	Condition mineA;
	Condition mineB;
	public TA(Lock lock, Condition mineA,Condition mineB) {
		this.lock = lock;
		this.mineA = mineA;
		this.mineB = mineB;
	}
	public void run(){
		for (int i=0;i<10;i++){
		//put code for TA here
		try{
			lock.lock();
			System.out.println("TA going first!");
			mineB.signal();
			mineA.await();
		}catch(InterruptedException e){}
		}
	}
}

class TB extends Thread{
	Lock lock ;
	Condition mineA;
	Condition mineB;
	public TB(Lock lock, Condition mineA,Condition mineB) {
		this.lock = lock;
		this.mineA = mineA;
		this.mineB = mineB;
	}
	public void run(){
		for (int i=0;i<10;i++){
		try{
			lock.lock();
			System.out.println("TB going second!");
			mineA.signal();
			mineB.await();
		}catch(InterruptedException e){}
		//put code for TB here
		}	

	}
}

Open in new window

0
 
blossomparkAuthor Commented:
thanks mnrz...will put in delay as suggested also
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.