How to avoid threads to starve - java

Suppose I have a hotel with m Rooms.
Guests (Threads) come in and out the whole time.
A Room can have lots of people inside, but only one Room will have people. For example:
Guest A (wants Room 1)
Guest B (wants Room 2)
Guest C (wants Room 1)
A can go to Room 1, once all rooms are empty;
B cannot go to Room 2 yet, given that there is another room with people still inside;
C can go to Room 1, because the Room C wants is the only Room with people inside;
Given that A and C leave Room 1, B should be able to go to Room 2
The last Guest to exit a room should stop every other Guests (avoiding them to come in while he is coming out) until it leaves, so the others can continue
How can I implement this somehow the threads will not starve?
For simplicity, suppose that, once the Guest comes inside a room, it sleeps for some seconds and then get out. Here is my (wrong) implementation:
import java.util.ArrayList;
import java.util.Random;
public class Guest extends Thread {
static Rooms rooms = new Rooms(5);
int id;
Guest(int id) {
this.id = id;
}
public void run() {
rooms.join(this);
nap();
rooms.quit(this);
}
public void nap() {
try {
sleep((new Random().nextInt(4000) + 1000));
} catch (InterruptedException e) {
}
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 20; i++) {
Thread t = new Guest(i);
t.start();
Thread.sleep((long) new Random().nextInt(1500) + 1000);
}
}
}
class Rooms {
Room[] rooms;
int busy;
Rooms(int m) {
busy = -1;
rooms = new Room[m + 1];
for (int i = 0; i < m + 1; i++)
rooms[i] = new Room();
}
void join(Guest h) {
if (busy == -1) {
busy = (new Random().nextInt(rooms.length));
}
rooms[busy].add(h);
System.out.println("Guest " + h.id + " came inside room " + busy + " with " + rooms[busy].size() + " people");
}
void quit(Guest h) {
if (rooms[busy].size() == 1) {
setHandler(busy, h);
} else {
rooms[busy].remove(h);
System.out
.println("Guest " + h.id + " came out of room " + busy + " with " + rooms[busy].size() + " people");
}
}
synchronized void setHandler(int numQuarto, Guest ultimo) {
System.out.println("(Last) Guest " + ultimo.id + " came out of room " + busy + " with "
+ rooms[numQuarto].size() + " people");
rooms[numQuarto].remove(ultimo);
busy = -1;
}
}
class Room extends ArrayList<Guest> {
}

To do this with threads -- which is highly artificial, but I suppose it is an exercise -- you need to learn how to make a Thread wait on a condition, and how to notify one or more Threads that the condition they are waiting for may have been satisfied. Conveniently, every object has methods wait(), notify(), and notifyAll() that serve these purposes.
One important consideration with wait / notify is that you must be careful to wait on and notify the correct object. Generally, that's not the Thread you want to be affected, but rather some shared object that all threads involved rely upon for mutual synchronization. In this particular case, it looks like Guest.rooms would do nicely.
The general idea would be that in Rooms.join(), the current thread tests whether it can immediately take a room. If so, it does, and continues as now. If not, however, it invokes wait() (on the Rooms instance, which at that point is this). Whenever that wait() returns, the thread must again check whether it can immediately take the room it wants; if not, it must wait again.
The other half would be in Rooms.quit(). Whenever a thread running that method is the last one out of the room, it must reset busy to indicate that no room is occupied, and then, importantly, invoke notifyAll() to let all threads waiting at that time know that there's a chance to get a room.
You will find that you need to employ proper synchronization for this. In particular, you can invoke wait() and notifyAll() (and notify()) only while holding the monitor of the target object (it will be released for the duration of the wait, and reacquired before wait() returns). You will also need to ensure that you properly synchronize all manipulation of shared objects, however, in this case mainly the Rooms and its members, without preventing threads from proceeding when otherwise they could. In particular, be aware that threads that sleep() do not for that reason release any monitors they may hold.
The rest is up to you. I've given you rather a lot more of a hint than maybe I should, but it truly is a bit tricky to learn how to use wait / notify properly.

You can't. Based on what you've given, other mechanisms would need to be implemented which guarantee no starvation can occur. For example,
Guests (Threads) come in and out the whole time.
So, it's possible that n threads come in for Room m possibly the whole time. It's possible, too, that during that time more threads come in wanting another room. However, they cannot access the room until Room m is first emptied (which may never actually happen). This can continue for any number of rooms and threads. This is the case even if...
For simplicity, suppose that, once the Guest comes inside a room, it
sleeps for some seconds and then get out.
And that's because...
C can go to Room 1, because the Room C wants is the only Room with
people inside;
Which implies that another thread may enter an already occupied room with one or more threads with t time left to sleep. The new thread goes to sleep and won't wake up until after the previous one. While sleeping n more threads may enter the room potentially causing other threads waiting for other rooms to starve.

Related

Implementing a simple turn-based game in Java using the wait-notify approach

I'm trying to implement a word game in Java, where each player takes turns extracting a number of random letters from a set, then trying to create a valid word with those letters. This is what I have so far (simplified for clarity's sake):
In the Game class, I start the game by running a thread for each player (and one for the timekeeper). I want the first player in the activePlayers list (which initially is the same as the players list) to make the first move, so I initialized the turn and turnIndex attributes to correspond to this player:
public void play()
{
this.turn = activePlayers.get(0); //the player who joined first goes first
this.turnIndex = 0; //the player's index in the ArrayList
for(Player player : players) {
new Thread(player).start();
}
new Thread(new Timekeeper()).start(); //keeps track of the game's duration
}
In the Player class, I want the players on stand-by to not do anything, and simply wait for the current player to finish their business, hence the first while loop. Then, when a player's turn has ended, I want that thread to yield the monitor to another player's thread and wait its next turn. This is how I decided to approach it:
private synchronized boolean submitWord() throws InterruptedException
{
while(game.turn != this)
{
System.out.println(this.name + " is waiting their turn...");
wait();
}
Thread.sleep(1000);
List<Tile> extracted = game.getBag().extractTiles(wordLength);
if(extracted.isEmpty())
return false; //if there are no more letters to extract, the thread ends its execution
//game logic goes here - creating and validating the word
//after this player is done, the next player makes their move
game.turnIndex++;
if(game.turnIndex >= game.activePlayers.size())
game.turnIndex = 0;
game.turn = game.activePlayers.get(game.turnIndex);
notifyAll();
return true;
}
#Override
public void run()
{
do {
try {
this.running = this.submitWord();
} catch(InterruptedException e) {
System.out.println("Something went wrong with " + this.name + "...");
e.printStackTrace();
}
} while(this.running);
game.activePlayers.remove(this); //the player is now inactive
if(game.winner == this)
System.out.println("Winner: " + this.name + " [" + this.score + " points]");
}
However, when I try to run the program, I get something like this:
Player 2 is waiting their turn...
Player 3 is waiting their turn...
1 seconds elapsed...
Player 1: AERIAL [36 points]
Player 1 is waiting their turn...
2 seconds elapsed...
3 seconds elapsed...
4 seconds elapsed...
5 seconds elapsed...
6 seconds elapsed...
Basically, the game doesn't move past Player 1's first try, and I get stuck in an infinite loop where nothing happens. Am I not using the wait() and notifyAll() methods properly? How should I make the player threads communicate with each other?
If I have understood your code correctly, that submitWord method belongs to the Player class. The keyword synchronized should be used to obtain the monitor of a shared resource to limit different threads from accessing the same resource at the same time and avoid race conditions.
In your case, you're synchronizing over a Player thread which is not the right design. You should synchronize instead over the shared resource which is the game object in this scenario. Besides, try to use synchronized blocks rather than entire synchronized methods, as the latter are more likely to block.
Within the Player's run method you should check whether the thread can acquire the game resource first with a synchronized block, if they do, then you can check whether it's the Player's turn by confronting the turn index of the game object with the Player's index. If it's not the Player's turn it invokes the wait() method; otherwise it carries on with its task by invoking submitWord.
Here, I've tweaked your code. You forgot a notify (or notifyAll) call when you were returning false in your submitWord method. That might have caused some stuck scenarios when there were no combinations available.
//Now, this method can be called only under the condition the the game's monitor lock has been already acquired. So, it can only be invoked within a synchronized block.
private boolean submitWord() {
List<Tile> extracted = game.getBag().extractTiles(wordLength);
if(extracted.isEmpty()){
//notify is more efficient than notifyAll as it causes less overhead by awakening only one random thread instead of all the ones waiting
this.game.notify();
//you were returning without notifying here... This might have caused some stucking scenarios...
return false;
}
//game logic goes here - creating and validating the word
//Rotating the turn
game.turnIndex = (this.game.turnIndex + 1) % this.game.activePlayers.size();
game.turn = game.activePlayers.get(game.turnIndex);
this.game.notify();
return true;
}
#Override
public void run() {
do {
synchronized(this.game){
if (this.game.indexTurn == this.index){
this.running = this.submitWord();
//It's more efficient to check here whether the player must be removed or not as you already own the game's lock
if (!this.running){
this.game.activePlayers.remove(this);
}
} else {
try {
this.game.wait();
} catch(InterruptedException e) {
System.out.println("Something went wrong with " + this.name + "...");
e.printStackTrace();
}
}
}
} while(this.running);
//you should re-acquire the game's lock here since you're modifying the set of players
//synchronized(this.game){
// this.game.activePlayers.remove(this);
//}
if(this.game.winner == this){
System.out.println("Winner: " + this.name + " [" + this.score + " points]");
}
}
Just a thought, but it could be that the sleep is happening within a synchronized method: Thread.sleep is blocking other thread also, working on other method, along with itself callled inside synchronized method

Thread executes too many times and causes race condition even though I'm using locks

I'm working on a multithread application for an exercise used to simulate a warehouse (similar to the producer consumer problem) however I'm running into some trouble with the program where increasing the number of consumer threads makes the program behave in unexpected ways.
The code:
I'm creating a producer thread called buyer which has as a goal to order precisely 10 orders from the warehouse each. To do this they have a shared object called warehouse on which a buyer can place an order, the order is then stored in a buffer in the shared object. After this the buyer sleeps for some time until it either tries again or all packs have been bought. The code to do this looks like this:
public void run() {
//Run until the thread has bought 10 packages, this ensures the thread
//will eventually stop execution automatically.
while(this.packsBought < 10) {
try {
//Sleep for a random amount of time between 1 and 50
//milliseconds.
Thread.sleep(this.rand.nextInt(49) + 1);
//Catch any interruptExceptions.
} catch (InterruptedException ex) {
//There is no problem if this exception is thrown, the thread
//will just make an order earlier than planned. that being said
//there should be no manner in which this exception is thrown.
}
//Create a new order.
Order order = new Order(this.rand.nextInt(3)+ 1,
this,
this.isPrime);
//Set the time at which the order was placed as now.
order.setOrderTime(System.currentTimeMillis());
//place the newly created order in the warehouse.
this.warehouse.placeOrder(order);
}
//Notify the thread has finished execution.
System.out.println("Thread: " + super.getName() + " has finished.");
}
As you can see the function placeOrder(Order order); is used to place an order at the warehouse. this function is responsible for placing the order in the queue based on some logic related to prime status. The function looks like this:
public void placeOrder(Order order) {
try{
//halt untill there are enough packs to handle an order.
this.notFullBuffer.acquire();
//Lock to signify the start of the critical section.
this.mutexBuffer.lock();
//Insert the order in the buffer depending on prime status.
if (order.isPrime()) {
//prime order, insert behind all prime orders in buffer.
//Enumerate all non prime orders in the list.
for (int i = inPrime; i < sizeOrderList - 1; i++) {
//Move the non prime order back 1 position in the list.
buffer[i + 1] = buffer[i];
}
// Insert the prime order.
buffer[inPrime++] = order;
} else {
//No prime order, insert behind all orders in buffer.
buffer[inPrime + inNormal++] = order;
}
//Notify the DispatchWorkers that a new order has been placed.
this.notEmptyBuffer.release();
//Catch any InterruptException that might occure.
} catch(InterruptedException e){
//Even though this isn't expected behavior, there is no reason to
//notify the user of this event or to preform any other action as
//the thread will just return to the queue before placing another
//error if it is still required to do so.
} finally {
//Unlock and finalize the critical section.
mutexBuffer.unlock();
}
}
The orders are consumed by workers which act as the consumer thread. The thread itself contains very simple code looping until all orders have been processed. In this loop a different function handleOrder(); is called on the same warehouse object which handles a single order from the buffer. It does so with the following code:
public void handleOrder(){
//Create a variable to store the order being handled.
Order toHandle = null;
try{
//wait until there is an order to handle.
this.notEmptyBuffer.acquire();
//Lock to signify the start of the critical section.
this.mutexBuffer.lock();
//obtain the first order to handle as the first element of the buffer
toHandle = buffer[0];
//move all buffer elementst back by 1 position.
for(int i = 1; i < sizeOrderList; i++){
buffer[i - 1] = buffer[i];
}
//set the last element in the buffer to null
buffer[sizeOrderList - 1] = null;
//We have obtained an order from the buffer and now we can handle it.
if(toHandle != null) {
int nPacks = toHandle.getnPacks();
//wait until the appropriate resources are available.
this.hasBoxes.acquire(nPacks);
this.hasTape.acquire(nPacks * 50);
//Now we can handle the order (Simulated by sleeping. Although
//in real live Amazon workers also have about 5ms of time per
//package).
Thread.sleep(5 * nPacks);
//Calculate the total time this order took.
long time = System.currentTimeMillis() -
toHandle.getOrderTime();
//Update the total waiting time for the buyer.
toHandle.getBuyer().setWaitingTime(time +
toHandle.getBuyer().getWaitingTime());
//Check if the order to handle is prime or not.
if(toHandle.isPrime()) {
//Decrement the position of which prime orders are
//inserted into the buffer.
inPrime--;
} else {
//Decrement the position of which normal orders are
//inserted into the buffer.
inNormal--;
}
//Print a message informing the user a new order was completed.
System.out.println("An order has been completed for: "
+ toHandle.getBuyer().getName());
//Notify the buyer he has sucsessfully ordered a new package.
toHandle.getBuyer().setPacksBought(
toHandle.getBuyer().getPacksBought() + 1);
}else {
//Notify the user there was a critical error obtaining the
//error to handle. (There shouldn't exist a case where this
//should happen but you never know.)
System.err.println("Something went wrong obtaining an order.");
}
//Notify the buyers that a new spot has been opened in the buffer.
this.notFullBuffer.release();
//Catch any interrupt exceptions.
} catch(InterruptedException e){
//This is expected behavior as it allows us to force the thread to
//revaluate it's main running loop when notifying it to finish
//execution.
} finally {
//Check if the current thread is locking the buffer lock. This is
//done as in the case of an interrupt we don't want to execute this
//code if the thread interrupted doesn't hold the lock as that
//would result in an exception we don't want.
if (mutexBuffer.isHeldByCurrentThread())
//Unlock the buffer lock.
mutexBuffer.unlock();
}
}
The problem:
To verify the functionallity of the program I use the output from the statement:
System.out.println("An order has been completed for: "
+ toHandle.getBuyer().getName());
from the handleOrder(); function. I place the whole output in a text file, remove all the lines which aren't added by this println(); statement and count the number of lines to know how many orders have been handled. I expect this value to be equal to the amount of threads times 10, however this is often not the case. Running tests I've noticed sometimes it does work and there are no problems but sometimes one or more buyer threads take more orders than they should. with 5 buyer threads there should be 50 outputs but I get anywhere from 50 to 60 lines (orders places).
Turning the amount of threads up to 30 increases the problem and now I can expect an increase of up to 50% more orders with some threads placing up to 30 orders.
Doing some research this is called a data-race and is caused by 2 threads accessing the same data at the same time while 1 of them writes to the data. This basically changes the data such that the other thread isn't working with the same data it expects to be working with.
My attempt:
I firmly believe ReentrantLocks are designed to handle situations like this as they should stop any thread from entering a section of code if another thread hasn't left it. Both the placeOrder(Order order); and handleOrder(); function make use of this mechanic. I'm therefor assuming I didn't implement this correctly. Here is a version of the project which is compileable and executable from a single file called Test.java. Would anyone be able to take a look at that or the code explained above and tell me what I'm doing wrong?
EDIT
I noticed there was a way a buyer could place more than 10 orders so I changed the code to:
/*
* The run method which is ran once the thread is started.
*/
public void run() {
//Run until the thread has bought 10 packages, this ensures the thread
//will eventually stop execution automatically.
for(packsBought = 0; packsBought < 10; packsBought++)
{
try {
//Sleep for a random amount of time between 1 and 50
//milliseconds.
Thread.sleep(this.rand.nextInt(49) + 1);
//Catch any interruptExceptions.
} catch (InterruptedException ex) {
//There is no problem if this exception is thrown, the thread
//will just make an order earlier than planned. that being said
//there should be no manner in which this exception is thrown.
}
//Create a new order.
Order order = new Order(this.rand.nextInt(3)+ 1,
this,
this.isPrime);
//Set the time at which the order was placed as now.
order.setOrderTime(System.currentTimeMillis());
//place the newly created order in the warehouse.
this.warehouse.placeOrder(order);
}
//Notify the thread has finished execution.
System.out.println("Thread: " + super.getName() + " has finished.");
}
in the buyers run(); function yet I'm still getting some threads which place over 10 orders. I also removed the update of the amount of packs bought in the handleOrder(); function as that is now unnecessary. here is an updated version of Test.java (where all classes are together for easy execution) There seems to be a different problem here.
There are some concurrency issues with the code, but the main bug is not related to them: it's in the block starting in line 512 on placeOrder
//Enumerate all non prime orders in the list.
for (int i = inPrime; i < sizeOrderList - 1; i++) {
//Move the non prime order back 1 position in the list.
buffer[i + 1] = buffer[i];
}
when there is only one normal order in the buffer, then inPrime value is 0, inNormal is 1, buffer[0] is the normal order and the rest of the buffer is null.
The code to move non primer orders, starts in index 0, and then does:
buffer[1] = buffer[0] //normal order in 0 get copied to 1
buffer[2] = buffer[1] //now its in 1, so it gets copied to 2
buffer[3] = buffer[2] //now its in 2 too, so it gets copied to 3
....
so it moves the normal order to buffer[1] but then it copies the contents filling all the buffer with that order.
To solve it you should copy the array in reverse order:
//Enumerate all non prime orders in the list.
for (int i = (sizeOrderList-1); i > inPrime; i--) {
//Move the non prime order back 1 position in the list.
buffer[i] = buffer[i-1];
}
As for the concurrency issues:
If you check a field on a thread, updated by another thread you should declare it as volatile. Thats the case of the run field in DispatcherWorker and ResourceSupplier. See: https://stackoverflow.com/a/8063587/11751648
You start interrupting the dispatcher threads (line 183) while they are still processing packages. So if they are stopped at 573, 574 or 579, they will throw an InterruptedException and not finish the processing (hence in the last code not always all packages are delivered). You could avoid this by checking that the buffer is empty before start interrupting dispatcher threads, calling warehouse.notFullBuffer.acquire(warehouse.sizeOrderList); on 175
When catching InterruptedException you should always call Thread.currentThread().interrupt(); the preserve the interrupted status of the Thread. See: https://stackoverflow.com/a/3976377/11751648
I believe you may be chasing ghosts. I'm not entirely sure why you're seeing more outputs than you're expecting, but the number of orders placed appears to be in order. Allow me to clarify:
I've added a Map<String,Integer> to the Warehouse class to map how many orders each thread places:
private Map<String,Integer> ordersPlaced = new TreeMap<>();
// Code omitted for brevity
public void placeOrder(Order order)
{
try
{
//halt untill there are enough packs to handle an order.
this.notFullBuffer.acquire();
//Lock to signify the start of the critical section.
this.mutexBuffer.lock();
ordersPlaced.merge(Thread.currentThread().getName(), 1, Integer::sum);
// Rest of method
}
I then added a for-loop to the main method to execute the code 100 times, and added the following code to the end of each iteration:
warehouse.ordersPlaced.forEach((thread, orders) -> System.out.printf(" %s - %d%n", thread, orders));
I placed a breakpoint inside the lambda expression, with condition orders != 10. This condition never triggered in the 100+ runs I executed. As far as I can tell, your code is working as intended. I've increased both nWorkers and nBuyers to 100 just to be sure.
I believe you're using ReentrantLock correctly, and I agree that it is probably the best choice for your use case.
referring at your code on pastebin
THE GENERIC PROBLEM:
In the function public void handleOrder() he sleep (line 582) Thread.sleep(5 * nPacks); is inside the lock(): unlock(): block.
With this position of sleep, it has no sense to have many DispatchWorker because n-1 will wait at line 559 this.mutexBuffer.lock() while one is sleeping at line 582.
THE BUG:
The bug is in line 173. You should remove it.
In your main() you join all buyers and this is correct. Then you try to stop the workers. The workers at this time are already running to complete orders that will be completed seconds after. You should only set worker.runThread(false); and then join the thead (possibly in two separate loops). This solution really waits for workers to complete orders. Interrupting the thread that is sleeping at line 582 will raise an InterruptedException and the following lines are skipped, in particular line 596 or 600 that update inPrime and in Normal counters generating unpredictable behaviours.
moving line 582 after line 633 and removing line 173 will solve the problem
HOW TO TEST:
My suggestion is to introduce a counter of all Packs boxes generated by supplier and a counter of all boxes ordered and finally check if generated boxes are equals at ordered plus that left in the whorehouse.

Why is synchronization not working properly within this code?

Over the past few days I have been reading articles about Multithreading and I have come across a simple task using multhithreading. This is the task:
Create an application which simulates the running race of 50 meters(in my code they are 10, does not matter). The number of runners should be 5 and you should name each runner thread. Print the winner. All the other threads should complete the race, as well. Print the time taken by each runner to complete the race and highlight the winner's time.
This is the code I've written:
public class Racer implements Runnable {
public static String winner;
public static int time = 0;
public void incrementTime() {
synchronized (Racer.class) {
time++;
}
}
public void race() {
for (int distance = 1; distance <= 10; distance++) {
incrementTime();
System.out.println("Distance covered by " + Thread.currentThread().getName() + " is " + distance + " meters.");
boolean finalDest = this.isTheRaceOver(distance);
if (finalDest) {
break;
}
}
}
private boolean isTheRaceOver(int finalDistance) {
boolean isRaceOver = false;
if (Racer.winner == null && finalDistance == 10) {
String winnerName = Thread.currentThread().getName();
Racer.winner = winnerName;
System.out.println("The winner is : " + Racer.winner + " with time " + time);
isRaceOver = true;
} else if (Racer.winner == null) {
isRaceOver = false;
} else if (finalDistance != 10) {
isRaceOver = false;
} else if (finalDistance == 10) {
System.out.println(Thread.currentThread().getName() + " is with time " + time);
}
return isRaceOver;
}
#Override
public void run() {
this.race();
}
}
public class RacerDemo {
public static void main(String[] args) {
Racer racer = new Racer();
Thread a = new Thread(racer, "A");
Thread b = new Thread(racer, "B");
Thread c = new Thread(racer, "C");
Thread d = new Thread(racer, "D");
Thread e = new Thread(racer, "E");
a.start();
b.start();
c.start();
d.start();
e.start();
}
}
One output is:
Distance covered by A is 1 meters.
Distance covered by C is 1 meters.
Distance covered by C is 2 meters.
Distance covered by C is 3 meters.
Distance covered by C is 4 meters.
Distance covered by C is 5 meters.
Distance covered by C is 6 meters.
Distance covered by C is 7 meters.
Distance covered by C is 8 meters.
Distance covered by C is 9 meters.
Distance covered by C is 10 meters.
The winner is : C with time 12 // should be 11 ?
Distance covered by B is 1 meters.
Distance covered by B is 2 meters.
...... and so on
The thing that bothers me is when it prints the time taken by each racer(thread) to cover the distance, it does not show the right time. I made incrementTime() synchronized, but the program does not work properly either. Can you tell me what is wrong? Where is my mistake?
Each runner increments the time, causing an inconsistent state. You should separate the racers from the actual race, which should probably be in a separate class.
Your problem occurs in the race method of the Racer Runnable, where each runner increments the static time field, thus causing the unexpected behavior.
In your implementation, time is shared by all the threads. So, if one thread increments is, the other thread will read that value, e.g.:
Thread 1 enters race() value of time is 0
Thread 1 calls incrementTime() changing the value to 1
Thread 2 enters race() value of time is 1
Thread 2 calls incrementTime() changing the value to 2
This will leave the time variable in an inconsistent state. To avoid this, you can try delaring time inside race() method so that each thread has its own time.
Every runner increments time and there is only a lock on the increments time method. Runner C finishes their race and calls the isRaceOver method. As c is going to get the time of 11, thread b runs the race method, sneaks in and increments time 1. As a result, c gets the time of 12 and prints out the time incorrectly. If your intention is for all runners to be able to increment the time, you have to make sure that only 1 thread is running race or IsTheRaceOver at a time.
You would get same result without synchronized block since you synchronized an integer which is atomic by default. Synchronized keyword is unnecessary so there is no synchronization at all.
Distance covered by A is 1 meters.
Distance covered by C is 1 meters.
Distance covered by C is 2 meters.
...
The winner is : C with time 12 // should be 11 ?
From your output it's clear that another thread was incremented time too. There might be another thread which incremented time right before you print the winner. To solve your problem, you have to synchronize both incrementTime and isTheRaceOver methods this way you will make sure another thread will not be able to increment time right before you print it.
But hold on: Synchronized block does not guarantee updates are visible to another threads which is called cache coherence. If you don't use volatile keywords when one thread updates a variable, it's not guaranteed that another thread will see it. For example even if you set the winner another thread may still see it as null.
Make sure you use volatile keyword or locks (which also use memory barriers) to guarantee that the updates will be visible to other threads.

Cyclic barrier Java, How to verify?

I am preparing for interviews and just want to prepare some basic threading examples and structures so that I can use them during my white board coding if I have to.
I was reading about CyclicBarrier and was just trying my hands at it, so I wrote a very simple code:
import java.util.concurrent.CyclicBarrier;
public class Threads
{
/**
* #param args
*/
public static void main(String[] args)
{
// ******************************************************************
// Using CyclicBarrier to make all threads wait at a point until all
// threads reach there
// ******************************************************************
barrier = new CyclicBarrier(N);
for (int i = 0; i < N; ++i)
{
new Thread(new CyclicBarrierWorker()).start();
}
// ******************************************************************
}
static class CyclicBarrierWorker implements Runnable
{
public void run()
{
try
{
long id = Thread.currentThread().getId();
System.out.println("I am thread " + id + " and I am waiting for my friends to arrive");
// Do Something in the Thread
Thread.sleep(1000*(int)(4*Math.random()*10));
// Now Wait till all the thread reaches this point
barrier.await();
}
catch (Exception e)
{
e.printStackTrace();
}
//Now do whatever else after all threads are released
long id1 = Thread.currentThread().getId();
System.out.println("Thread:"+id1+" We all got released ..hurray!!");
System.out.println("We all got released ..hurray!!");
}
}
final static int N = 4;
static CyclicBarrier barrier = null;
}
You can copy paste it as is and run in your compiler.
What I want to verify is that indeed all threads wait at this point in code:
barrier.await();
I put some wait and was hoping that I would see 4 statements appear one after other in a sequential fashion on the console, followed by 'outburst' of "released..hurray" statement. But I am seeing outburst of all the statements together no matter what I select as the sleep.
Am I missing something here ?
Thanks
P.S: Is there an online editor like http://codepad.org/F01xIhLl where I can just put Java code and hit a button to run a throw away code ? . I found some which require some configuration before I can run any code.
The code looks fine, but it might be more enlightening to write to System.out before the sleep. Consider this in run():
long id = Thread.currentThread().getId();
System.out.println("I am thread " + id + " and I am waiting for my friends to arrive");
// Do Something in the Thread
Thread.sleep(1000*8);
On my machine, I still see a burst, but it is clear that the threads are blocked on the barrier.
if you want to avoid the first burst use a random in the sleep
Thread.sleep(1000*(int)(8*Math.rand()));
I put some wait and was hoping that I
would see 4 statements appear one
after other in a sequential fashion on
the console, followed by 'outburst' of
"released..hurray" statement. But I am
seeing outburst of all the statements
together no matter what I select as
the sleep.
The behavior I'm observing is that all the threads created, sleep for approximately the same amount of time. Remember that other threads can perform their work in the interim, and will therefore get scheduled; since all threads created sleep for the same amount of time, there is very little difference between the instants of time when the System.out.println calls are invoked.
Edit: The other answer of sleeping of a random amount of time will aid in understanding the concept of a barrier better, for it would guarantee (to some extent) the possibility of multiple threads arriving at the barrier at different instants of time.

controlling threads flow

I had a task to write simple game simulating two players picking up 1-3 matches one after another until the pile is gone. I managed to do it for computer choosing random value of matches but now I'd like to go further and allow humans to play the game. Here's what I already have : http://paste.pocoo.org/show/201761/
Class Player is a computer player, and PlayerMan should be human being. Problem is, that thread of PlayerMan should wait until proper value of matches is given but I cannot make it work this way. Logic is as follows: thread runs until matches equals to zero. If player number is correct at the moment function pickMatches() is called. After decreasing number of matches on table, thread should wait and another thread should be notified. I know I must use wait() and notify() but I can't place them right.
Class Shared keeps the value of current player, and also amount of matches.
public void suspendThread() {
suspended = true;
}
public void resumeThread() {
suspended = false;
}
#Override
public void run(){
int matches=1;
int which = 0;
int tmp=0;
Shared data = this.selectData();
String name = this.returnName();
int number = this.getNumber();
while(data.getMatches() != 0){
while(!suspended){
try{
which = data.getCurrent();
if(number == which){
matches = pickMatches();
tmp = data.getMatches() - matches;
data.setMatches(tmp, number);
if(data.getMatches() == 0){
System.out.println(" "+
name+" takes "+matches+" matches.");
System.out.println("Winner is player: "+name);
stop();
}
System.out.println(" "+
name+" takes "+matches+" matches.");
if(number != 0){
data.setCurrent(0);
}
else{
data.setCurrent(1);
}
}
this.suspendThread();
notifyAll();
wait();
}catch(InterruptedException exc) {}
}
}
}
#Override
synchronized public int pickMatches(){
Scanner scanner = new Scanner(System.in);
int n = 0;
Shared data = this.selectData();
System.out.println("Choose amount of matches (from 1 to 3): ");
if(data.getMatches() == 1){
System.out.println("There's only 1 match left !");
while(n != 1){
n = scanner.nextInt();
}
}
else{
do{
n = scanner.nextInt();
}
while(n <= 1 && n >= 3);
}
return n;
}
}
Well, let me first say that I think you are making this hardier than you need to. If it were me, I would create a 'GameMaster' class whose job it is to loop and tell each player when their turn comes up. Your player classes wouldn't have loops, just a takeTurn method. This way you can remove the waiting/notifying behavior from your player classes.
If you wish to keep the design you have, I would still get rid of the wait/notify and use a Semaphore. Check the docs for proper usage, but the gist is that you would remove the suspend/resume methods and have a acquire() call at the top of your loop and release at the bottom. Just make sure fairness is set to true in the constructor, that way you won't have to worry about a player taking two turns in a row by acquiring the semaphore lock twice in a row.
Ok, so I managed to do it without wait() etc.
http://paste.pocoo.org/show/201966/
When you find yourself having to set up communication between threads to synchronize their execution, just so that a specified sequence of events takes place (such as taking turns playing a game), it's a good sign that you may have more threads than you need.
In this case, consider a single thread that executes a takeTurn() method on various extensions of a Player class might make life easier for you. You could make Player an abstract base class that mandates .takeTurn(), then have HumanPlayer and MachinePlayer classes encapsulate the code that makes sense for each type of player inside that method. This should make extension to larger numbers of players relatively trivial as compared to lots of wait() and notify().

Categories