Good day!
I’ve meet problems with synchronizing threads in Java.
I have 3 processes ( i keep them in ConcurrentHashMap< Integer, Integer > man ) and 4 resources ( i keep them in ConcurrentHashMap< Integer, Integer > resourses ).
Each process can hold only 2 immediate resources. For example man[0] can hold only resources[0] and resources[1], man[1] can hold only resources[1] and resources[2] and etc.
So i have few situations when thread must wait till other threads will not release their resources. So this thread goes to wait… And it doesn’t wake when i call notifyAll()!
What is wrong with my logic?
Here is my code:
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Philos
{
private Thread thisThread;
public Philos()
{
for ( int i = 1; i <= 4; i++ ) //Init processeses and resourses.
{
resourses.put( i, 0 ); //Each is free.
man.put(i, 0);
}
}
public void startThread( final int i )
{
thisThread = new Thread()
{
public void run()
{
try {
System.out.println(Thread.currentThread().getName());
Eat( i ); //Proc try to start work
show( i, "Eat" ); //Show res and procs
finishEat( i ); //Release resourses.
show( i, "Release" );
thisThread.interrupt(); //Finish threads
} catch (InterruptedException ex) {
Logger.getLogger(Philos.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
thisThread.start();
}
private synchronized void Eat( int i ) throws InterruptedException
{
testEat ( i ); //Try to work.
if ( !( man.get(i) == 1 ) ) //If proc are not working
{
System.out.printf("%d must wait\n", i);
synchronized( Thread.currentThread() ) //Put synchronize block to wait thread
{
Thread.currentThread().wait(); //Thread must wait
System.out.println("Notifyied");
}
}
}
private synchronized void finishEat( int i ) throws InterruptedException
{
man.put( i, 0 ); //Release proc
resourses.put(i, 0); //Release resourses of proc
resourses.put(i+1, 0);
}
private synchronized void testEat( int i ) throws InterruptedException
{
System.out.printf("Test %d\n",i);
if ( ( left(i) == 0 ) && ( right(i) == 0 ) ) //If resourses availible
{
man.put( i, 1 ); //Proc is busy
resourses.put(i, 1); //Resourses are busy
resourses.put(i+1, 1);
synchronized( Thread.currentThread() )
{
Thread.currentThread().notifyAll(); //Notify al threads
}
}
}
private int left( int i ) //Check left resourse.
{
return (resourses.get(i));
}
private int right( int i ) //Check right resourse.
{
return (resourses.get(i+1));
}
private synchronized void show( int i, String info ) //Show info about resourses and proc
{
System.out.printf("\nid = %d, [%s]\n", i, info );
System.out.println("Work[R]:");
for ( int j = 1; j <= 4; j++ ) //Res
{
System.out.printf( "%d ", resourses.get(j) );
}
System.out.println();
for ( int j = 1; j <= 4; j++ ) //Proc
{
System.out.printf( " %d", man.get(j) );
}
System.out.println();
}
private ConcurrentHashMap< Integer, Integer > resourses = new ConcurrentHashMap< Integer, Integer >();
private ConcurrentHashMap< Integer, Integer > man = new ConcurrentHashMap< Integer, Integer >();
}
You’re calling
wait()andnotifyAll()on aThreadobject. That’s not the way of doing things – you call it on some common object which all the relevant threads hold.The fact that you’re only synchronizing on the current thread in each case is also meaningless – nothing else is going to synchronize on that thread, so the synchronization is pointless.
You need to determine the common objects to synchronize/wait/notify. Typically I prefer to create separate objects solely for this purpose, but you can reuse existing objects too.
(I would also advise you not to call
Thread.interrupt– it’s unclear to me why you’re doing that here…)EDIT: As mentioned in comments, look at the higher-level abstractions in java.util.concurrent, such as
Semaphore, for a possibly-simpler way of achieving your goal.