Create a program that simulates training at an athletic stadium,
there is one track in the stadium that can be used by up to 5 people at a time
and the coach does not allow that number to exceed, but when some of the athletes finish their run (2sec)
and free up space then notify other athlete for running.
After 2 seconds, all processes are frozen
My question is, could anyone explain to me why something like this does not work and how to handle this problem?
class JoggingTrack {
public int numOfAthlete;
public JoggingTrack() {
this.numOfAthlete = 0;
}
#Override
public String toString() {
return "\nNumber of Athlete: " + numOfAthlete + "\n";
}
}
class Athlete extends Thread {
private JoggingTrack track;
private boolean running;
public Athlete(JoggingTrack s) {
this.track = s;
this.running = false;
}
public synchronized boolean thereIsSpace() {
if(track.numOfAthlete < 5) {
return true;
}
return false;
}
public synchronized void addAthlete() {
track.numOfAthlete++;
this.running = true;
}
public synchronized void removeAthlete() {
track.numOfAthlete--;
this.running = false;
}
#Override
public void run() {
try {
while(true) {
while(!this.thereIsSpace()) {
wait();
}
while(!this.running) {
addAthlete();
sleep(2000);
}
while(this.running) {
removeAthlete();
notify();
}
}
} catch (Exception e) {
}
}
}
public class Program {
static JoggingTrack track;
static Athlete[] a;
public static void main(String[] args) {
track = new JoggingTrack();
a = new Athlete[10];
for(int i = 0; i < 10; i++) {
a[i] = new Athlete(track);
a[i].start();
}
while(true) {
try {
System.out.println(track);
Thread.sleep(500);
} catch (Exception e) {
}
}
}
}
A lot of issues with this.
Your methods are in the wrong place. The synchronized keyword synchronizes on an instance of the class, not across multiple instances. So your remove and add functions on different athletes would cause race conditions. These functions should be moved to the Track object, because all athletes are using the same track (so should your isThereSpace function). At the same time, you should not be directly accessing the member variables of Track in Athlete, use a getter for it instead.
Secondly, you use of wait and notify are wrong. They leave lots of holes for race conditions, although it may work most of the time. And this isn't really a good place for using them- a counting semaphore in the Track class would be a better solution- its exactly what counting semaphores are made for. Look at the Semaphore class for more details. Its basically a lock that will allow N owners of the lock at a time, and block additional requesters until an owner releases it.
Your threads are waiting forever, because they are waiting on some object (their instance itself), and nobody ever notify-es them, using the right instance.
One way to fix this is to have all athlete-s to synchronize/wait/notify on the same object, in example, the JoggingTrack. So that an athlete will wait on the track with track.wait(), and when an athlete is done running, it will call track.notify() , and then a waiting athlete will be waken up.
Then there are other issues as noted by Gabe-
Once you fix the first issue, you will find the race conditions- eg. too many threads all start running even though there are some checks (thereIsSpace) in place.
My question is, could anyone explain to me why something like this does not work and how to handle this problem?
Debugging multithreaded programs is hard. A thread-dump might help and println-debugging might also be helpful however they can cause the problem to migrate so it should be used with caution.
In your case, you are confusing your objects. Think about
Athlete.thereIsSpace() and Athlete.addAthlete(...). Does that make any sense? Does an athlete have space? Do you add an athlete to an athlete? Sometimes the object names don't help you make these sorts of evaluations but in this case, they do. It is the JoggingTrack that has space and that an athlete is added to.
When you are dealing with multiple threads, you need to worry about data sharing. If one thread does track.numOfAthlete++;, how will other threads see the update? They aren't sharing memory by default. Also ++ is actually 3 operations (read, increment, write) and you need to worry about multiple threads running the ++ at the same moment. You will need to use a synchronized block to ensure memory updates or use other concurrent classes such as AtomicInteger or a Semaphore which take care of the locking and data-sharing for you. Also, more generally, you really should not modify another object's fields in this way.
Lastly, you are confused about how wait/notify work. First of all, they only work if they are inside a synchronized block or method so I think the code you've posted won't compile. In your case, the thing that the multiple Athletes are contending for is the JoggingTrack, so the track needs to have the synchronized keyword and not the Athlete. The Athlete is waiting for the JoggingTrack to get space. No one is waiting for the athlete. Something like:
public class JoggingTrack {
public synchronized boolean thereIsSpace() {
return (numOfAthletes < 5);
}
public synchronized void addAthlete() {
numOfAthletes++;
}
...
Also, like the ++ case, you need to be really careful about race conditions in your code. No, not jogging races but programming races. For example, what happens if 2 athletes both go to do the following logic at precisely the same time:
while (!track.thereIsSpace()) {
track.wait();
}
addAthlete();
Both athletes might call thereIsSpace() which returns true (because no one has been added yet). Then both go ahead and add themselves to the track. That would increase the number of athletes by 2 and maybe exceed the 5 limit. These sorts of races-conditions happen every time unless you are in a synchronized block.
The JoggingTrack could instead have code like:
public synchronized void addIfSpaceOrWait() {
while (numOfAthletes >= 5) {
wait();
}
numOfAthletes++;
}
Then the althetes would do:
track.addIfSpaceOrWait();
addAthlete();
This code has no race condition because only one athlete will get the synchronized lock on the track at one time -- java guarantees it. Both of them can call that at the same time and one will return and the other will wait.
Couple other random comments:
You should never do a catch (Exception e) {}. Just doing an e.printStackStrace() is bad enough but not seeing your errors is really going to confuse you ability to debug your program. I will hope you just did that for your post. :-)
I love the JoggingTrack object name but whenever you reference it, it should be joggingTrack or maybe track. Be careful of JoggingTrack s.
An Athlete should not extend thread. It isn't a thread. It should implement Runnable. This is a FAQ.
Related
This program attempts to print numbers 1 to 10 in a sequential manner, 1 thread prints odd numbers and the second threads prints even numbers.
I have been reading JCIP book and it says:
Ensure that the state variables making up the condition predicate are guarded by the lock associated with the condition queue.
In the below program, the condition queue will correspond to static member 'obj1' while the state variable that makes up the condition predicate is static volatile member 'count'. (let me know if I am wrong in the interpretation of condition, state variable, condition predicate)
The below program works correctly but is clearly violating the above idiom. Have I understood what the author is trying to say correctly? Is the below code really a poor programming practice (which happens to work correctly)
Can you give me an example where not following the above idiom will make me run into problems?
public class OddEvenSynchronized implements Runnable {
static Object obj1 = new Object(); // monitor to share data
static volatile int count =1; // condition predicate
boolean isEven;
public OddEvenSynchronized(boolean isEven) { //constructor
this.isEven=isEven;
}
public void run (){
while (count<=10){
if (this.isEven == true){
printEven(); //print an even number
}
else{
printOdd(); //print an odd number
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread (new OddEvenSynchronized(true));
Thread t2 = new Thread (new OddEvenSynchronized(false));
//start the 2 threads
t1.start();
t2.start();
}
void printEven(){
synchronized (obj1) {
while (count%2 != 0){
try{
obj1.wait();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("Even"+count);
count++; //unguarded increment (violation)
synchronized (obj1) {
obj1.notifyAll();
}
} //end method
void printOdd(){
synchronized (obj1) {
while (count%2 == 0){
try{
obj1.wait();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("Odd"+count);
count++; //unguarded increment (violation)
synchronized (obj1) {
obj1.notifyAll();
}
} //end method
} //end class
Do not read from or write to count if you're not synchronized on obj1. That's a no no! The prints and the increments should be done from inside synchronized blocks.
synchronized (obj1) {
while (count%2 != 0){
try {
obj1.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Even"+count);
}
synchronized (obj1) {
count++;
obj1.notifyAll();
}
You'll notice that there's no reason to drop the synchronization now. Combine the two blocks.
synchronized (obj1) {
while (count%2 != 0){
try {
obj1.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Even"+count);
count++;
obj1.notifyAll();
}
The below program works correctly but is clearly violating the above idiom.
The insidious danger of multithreaded programming is that a buggy program can appear to work correctly most of the time. Race conditions can be quite devious because they often require very tight timing conditions which rarely happen.
It's really, really important to follow the rules to the letter. It's very difficult to get multithreaded programming right. It's a near certainty that any time you deviate from the rules and try to be clever you will introduce subtle bugs.
The only reason I have been able to come up with for this question, as hinted by my discussion with John Kugelman in his answer (please correct if something is wrong):
1st Key insight: In Java, there is only one condition queue associated with the object's monitor. And although they share the condition queue, there condition predicates are different. This sharing results in unnecessary wakeup ->check condition predicate -> sleep again. So although inefficient, they will still behave as kind of separate condition queues if coded properly ( while ( condition predicate ) { thread.wait() } )
In the above program, the condition predicates
count%2 == 0
count%2 != 0
are different, although they are part of the same condition queue (i.e. doing a notify() on this object's monitor will wake both of them, however only one would be able to proceed at a time).
The 2nd key insight:
The volatile count variable ensure memory visibility.
Conclusion:
As soon as we introduce another thread with the same condition predicate, the program will be susceptible to race conditions (if not other defects).
Also, note that usually wait() notify() mechanism is employed for object with same condition predicated, for example, waiting for a resource lock. The above program is usually used in interviews and I doubt if it would be common in real-life code.
So, if there are two or more threads in the same condition queue with different condition predicates, and the condition predicate variable is volatile (and hence ensures memory visibility), then ignoring the above advice can produce a correct program. Although this is of little significance, this really helped me understand multi-threading better.
I am fairly new to JAVA and especially concurrency, so probably/hopefully this is fairly straight forward problem.
Basically from my main thread I have this:
public void playerTurn(Move move)
{
// Wait until able to move
while( !gameRoom.game.getCurrentPlayer().getAllowMove() )
{
try {
Thread.sleep(200);
trace("waiting for player to be available");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
gameRoom.getGame().handle(move);
}
gameRoom.getGame() is on its own thread.
gameRoom.getGame().handle() is synchronized
gameRoom.game.getCurrentPlayer() is on a varible of gameRoom.getGame(), it is in the same thread
allowMoves is set to false as soon as handle(move) is called, and back to true once it has finished processing the move.
I call playerTurn() multiple times. I actually call it from a SmartFoxServer extension, as and when it receives a request, often in quick succession.
My problem is, most times it works. However SOMETIMES it is issuing multiple handle(move) calls even though allowMoves should be false. Its not waiting for it to be true again. I thought its possible that the game thread didn't have a chance to set allowMoves before another handle(move) was called. I added volatile to allowMoves, and ensured the functions on the game thread were set to synchronized. But the problem is still happening.
These are in my Game class:
synchronized public void handle(Object msg)
{
lastMessage = msg;
notify();
}
synchronized public Move move() throws InterruptedException
{
while (true)
{
allowMoves = true;
System.out.print(" waiting for move()...");
wait();
allowMoves = false;
if (lastMessage instanceof Move)
{
System.out.print(" process move()...");
Move m = (Move) lastMessage;
return m;
}
}
}
public volatile boolean allowMoves;
synchronized public boolean getAllowMoves()
{
return allowMoves;
}
As I said, I am new to this and probably a little ahead of myself (as per usual, but its kinda my style to jump into the deep end, great for a quick learning curve anyway).
Cheers for your help.
Not sure if this will help, but what if you will use AtomicBoolean instead of synchronized and volatile? It says that it is lock-free and thread-safe.
The Problem is you are using synchronized method on two different objects.
gameRoom.game.getCurrentPlayer().getAllowMove()<-- This is synchronized on
CurrentPlayer instance.
gameRoom.getGame().handle(move)<-- This is synchronized on `gameRoom.getGame()`
This is your issue. You don't need synchronized keyword for getAllowMoves since field is volatile as volatile guarantees visibility semantics.
public boolean getAllowMoves() {
return allowMoves;
}
there is the primitive, dedicated for resource management - Semaphore
you need to
create semaphore with permits set to 1
use acquire when looking for a move
use release after move is complete
so you will never face that 2 concurrent invocations of handle method appear.
I am working on a game using the thread-per-client model. The game operates so that every half a second all of the players need to be updated. The updates all have to happen within the half a second interval, so they need to all be executed at the same time. My idea is to have a class that keeps track of when the "global update" needs to happen and then when the time comes, go through all of the players and tell it to update:
for(Player p : currentPlayers) {
p.update();
}
The problem is that since every player has their own thread, I want the player to take advantage of that fact since it is already there. If I go through the updates from a different class, then there is one thread executing what a couple hundred threads could be doing individually. How can I design it so that if a thread calls method 'update()' in class Player, a different thread than the one that called it executes it, or perhaps a different approach that can achieve the same goal?
If you need any clarification, please ask! Thanks a lot!
UPDATE: What do you guys think of this (I can't figure out how to format long amounts of code in posts!):
UPDATE 2: Just realized I would need to know when all of the players finish updating to reset the last time...
public class PseudoExample implements Runnable
{
// Assume 'players' is full of active players.
private Player[] players = new Player[100];
private long lastUpdate = System.currentTimeMillis();
public void run()
{
while (true)
{
if (System.currentTimeMillis() - lastUpdate >= 500)
{
for (Player p : players)
{
p.update = true;
}
}
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
}
}
}
private class Player implements Runnable
{
private boolean update = false;
public void run()
{
while (true)
{
if (update)
{
// Do updating here ...
}
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
}
}
}
}
}
I think the best way to handle this would be instead of calling p.update(), you could send an asynchronous message to p. This would use the Handler functionality. This is probably the cleanest way, although I believe some (likely trivial) overhead will occur from the message passing.
So, in your ticking thread (i.e. the one that calls the global update), you would have a reference to a Handler object for each client thread. Then, you look would look like
for (Player p : currentPlayers) {
p.handler().sendMessage(); // this isn't exactly the syntax
}
and in your Player, you would have a PlayerHandler object that extends Handler and overrides handleMessage(Message).
EDIT: the comments on the question are good ones - don't use more threads than you need to. They might seem to be the "right" abstraction, but they introduce a ton of potentially tricky issues. If all of your computation needs to be done in between ticks, it might not matter whether it's done sequentially or not.
In a legacy application I have a Vector that keeps a chronological list of files to process and multiple threads ask it for the next file to process. (Note that I realize that there are likely better collections to use (feel free to suggest), but I don't have time for a change of that magnitude right now.)
At a scheduled interval, another thread checks the working directory to see if any files appear to have been orphaned because something went wrong. The method called by this thread occasionally throws a ConcurrentModificationException if the system is abnormally busy. So I know that at least two threads are trying to use the Vector at once.
Here is the code. I believe the issue is the use of the clone() on the returned Vector.
private synchronized boolean isFileInDataStore( File fileToCheck ){
boolean inFile = false;
for( File wf : (Vector<File>)m_dataStore.getFileList().clone() ){
File zipName = new File( Tools.replaceFileExtension(fileToCheck.getAbsolutePath(), ZIP_EXTENSION) );
if(wf.getAbsolutePath().equals(zipName.getAbsolutePath()) ){
inFile = true;
break;
}
}
return inFile;
}
The getFileList() method is as follows:
public synchronized Vector<File> getFileList() {
synchronized(fileList){
return fileList;
}
}
As a quick fix, would changing the getFileList method to return a copy of the vector as follows suffice?
public synchronized Vector<File> getFileListCopy() {
synchronized(fileList){
return (Vector<File>)fileList.clone();
}
}
I must admit that I am generally confused by the use of synchronized in Java as it pertains to collections, as simply declaring the method as such is not enough. As a bonus question, is declaring the method as synchronized and wrapping the return call with another synchronized block just crazy coding? Looks redundant.
EDIT: Here are the other methods which touch the list.
public synchronized boolean addFile(File aFile) {
boolean added = false;
synchronized(fileList){
if( !fileList.contains(aFile) ){
added = fileList.add(aFile);
}
}
notifyAll();
return added;
}
public synchronized void removeFile( File dirToImport, File aFile ) {
if(aFile!=null){
synchronized(fileList){
fileList.remove(aFile);
}
// Create a dummy list so I can synchronize it.
List<File> zipFiles = new ArrayList<File>();
synchronized(zipFiles){
// Populate with actual list
zipFiles = (List<File>)diodeTable.get(dirToImport);
if(zipFiles!=null){
zipFiles.remove(aFile);
// Repopulate list if the number falls below the number of importer threads.
if( zipFiles.size()<importerThreadCount ){
diodeTable.put(dirToImport, getFileList( dirToImport ));
}
}
}
notifyAll();
}
}
Basically, there are two separate issues here: sycnhronization and ConcurrentModificationException. Vector in contrast to e.g. ArrayList is synchronized internally so basic operation like add() or get() do not need synchronization. But you can get ConcurrentModificationException even from a single thread if you are iterating over a Vector and modify it in the meantime, e.g. by inserting an element. So, if you performed a modifying operation inside your for loop, you could break the Vector even with a single thread. Now, if you return your Vector outside of your class, you don't prevent anyone from modifyuing it without proper synchronization in their code. Synchronization on fileList in the original version of getFileList() is pointless. Returning a copy instead of original could help, as could using a collection which allows modification while iterating, like CopyOnWriteArrayList (but do note the additional cost of modifications, it may be a showstopper in some cases).
"I am generally confused by the use of synchronized in Java as it
pertains to collections, as simply declaring the method as such is not
enough"
Correct. synchronized on a method means that only one thread at a time may enter the method. But if the same collection is visible from multiple methods, then this doesn't help much.
To prevent two threads accessing the same collection at the same time, they need to synchronize on the same object - e.g. the collection itself. You have done this in some of your methods, but isFileInDataStore appears to access a collection returned by getFileList without synchronizing on it.
Note that obtaining the collection in a synchronized manner, as you have done in getFileList, isn't enough - it's the accessing that needs synchronizing. Cloning the collection would (probably) fix the issue if you only need read-access.
As well as looking at synchronizing, I suggest you track down which threads are involved - e.g. print out the call stack of the exception and/or use a debugger. It's better to really understand what's going on than to just synchronize and clone until the errors go away!
Where does the m_dataStore get updated? That's a likely culprit if it's not synchronized.
First, you should move your logic to whatever class is m_dataStore if you haven't.
Once you've done that, make your list final, and synchronize on it ONLY if you are modifying its elements. Threads that only need to read it, don't need synchronized access. They may end up polling an outdated list, but I suppose that is not a problem. This gets you increased performance.
As far as I can tell, you would only need to synchronize when adding and removing, and only need to lock your list.
e.g.
package answer;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Example {
public static void main(String[] args)
{
Example c = new Example();
c.runit();
}
public void runit()
{
Thread.currentThread().setName("Thread-1");
new Thread("Thread-2")
{
#Override
public void run() {
test1(true);
}
}.start();
// Force a scenario where Thread-1 allows Thread-2 to acquire the lock
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(Example.class.getName()).log(Level.SEVERE, null, ex);
}
// At this point, Thread-2 has acquired the lock, but it has entered its wait() method, releasing the lock
test1(false);
}
public synchronized void test1(boolean wait)
{
System.out.println( Thread.currentThread().getName() + " : Starting...");
try {
if (wait)
{
// Apparently the current thread is supposed to wait for some other thread to do something...
wait();
} else {
// The current thread is supposed to keep running with the lock
doSomeWorkThatRequiresALockLikeRemoveOrAdd();
System.out.println( Thread.currentThread().getName() + " : Our work is done. About to wake up the other thread(s) in 2s...");
Thread.sleep(2000);
// Tell Thread-2 that it we have done our work and that they don't have to spare the CPU anymore.
// This essentially tells it "hey don't wait anymore, start checking if you can get the lock"
// Try commenting this line and you will see that Thread-2 never wakes up...
notifyAll();
// This should show you that Thread-1 will still have the lock at this point (even after calling notifyAll).
//Thread-2 will not print "after wait/notify" for as long as Thread-1 is running this method. The lock is still owned by Thread-1.
Thread.sleep(1000);
}
System.out.println( Thread.currentThread().getName() + " : after wait/notify");
} catch (InterruptedException ex) {
Logger.getLogger(Example.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void doSomeWorkThatRequiresALockLikeRemoveOrAdd()
{
// Do some work that requires a lock like remove or add
}
}
I have an unusual problem.
I have a function, operation in this function can be done by two threads at a time.
static int iCount = 1;
public synchronized void myFunct(){
while(iCount >= 3)
{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
iCount++;
//Do Stuffs
//After operation decrement count
iCount --;
notifyAll();
}
What i am trying to do is, i want to allow only two threads to do some operation, and other threads must wait.
But here first two threads increment the count and does the operation and other threads go for an wait state but do not get the notification.
I guess i am overlooking something.
Sounds like you want to use a Semaphore, you always call acquire() before doing your operation, and then release() in a finally block.
private static final Semphore semaphore = new Semaphore(2);
public static void myFunct() throws InterruptedException {
semaphore.aquire();
try {
// do stuff
} finally {
semaphore.release();
}
}
Your function is synchronized, so only one thread at a time can be in it.
I'm not sure I understand your question... But if you want to allow two threads to go somewhere at once, have a look at Semaphore.
Is this a singleton class?
If not then it's a problem because many concurrent instances may change the value of icounter and in addition they will block on it forever because no thread will be able to call notify on their instance object.
Anyway you should move the sync inside the function and lock iCount and not the instance, also make it volatile.
public void myFunct(){
synchronized(iCount) {
while(iCount >= 3)
{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
iCount++;
}
//Do Stuffs
//After operation decrement count
synchronized(iCount) {
iCount--;
}
notifyAll();
Why aren't you just using a Semaphore?
An alternative might be to use a ThreadPoolExecutor with a maximum of two threads.
You need java.util.concurrent.Semaphore, initialized with 2 permits.
As for your current code - threads may cache values of variables. Try adding the volatile keyword.
There are many problems with this code. Among them:
You have no real control on the number of threads running myFunct, since the method is synchronized on the instance level, while the counter is static. So N different threads operating on N different instances may run the same method concurrently.
Manipulating the counter by multiple threads is not thread safe. Consider synchronizing it or using AtomicInteger.
Regarding the limit on the number of threads, consider using the Semaphore class.