美好的一天!
我遇到了同步线程的问题。我正在编写类似晚餐哲学家的程序。我有几个进程(例如3个)和资源(例如4个)。每个进程只能使用2个免费资源。这意味着第一个流程只能用于第一和第二资源等。
我决定使用信号量作为我的目标。问题是仍然没有同步。例如,如果第一个和第三个进程正在使用资源,那么第二个进程必须等到他的资源不会被释放。在我的程序中,有时它会发生......有时它不会。
有什么问题?我该如何解决?
代码在这里:
public class Sem
{
public Sem()
{
available = new ConcurrentHashMap< Integer, Semaphore >();//Resources.
for ( int i = 1; i <= 4; i++)
{
available.put( i, new Semaphore(1, true) );//Each resource contains semaphore.
}
}
public void start( final int id )
{
thisThread = new Thread()
{
public void run()
{
try
{
work( id ); //Try to take resourses.
Thread.currentThread().sleep(1000);
release( id ); //Release resources.
} catch (InterruptedException ex) {
Logger.getLogger(Sem.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
thisThread.start();
}
public synchronized void work( int id ) throws InterruptedException
{
available.get(id).acquire(); //Try to take resourse[id] and resourse[id+1]
available.get(id+1).acquire(); //Thread is blocking till it will be possible.
System.out.printf("Acquired [%s], id = %d\n",Thread.currentThread().getName(), id);
}
public void release( int id )
{
available.get(id).release(); //Release resources which hava been captured by thread.
available.get(id+1).release(); //After this other thread can take these resourses.
System.out.printf("Released [%s], id = %d\n",Thread.currentThread().getName(), id);
}
private ConcurrentHashMap< Integer, Semaphore > available; //Integer - id of thread[1..4]; Semaphore - is gate with param (1)
//Available - map of resources which can be busy by processes.
Thread thisThread;
}
我这样开始这个程序:
Sem sem = new Sem();
sem.start(1);
sem.start(2);
sem.start(3);
我输出的消息很少,但我最喜欢的是:
Acquired [Thread-1], id = 1
Acquired [Thread-3], id = 3
Released [Thread-1], id = 1
Acquired [Thread-2], id = 2
Released [Thread-3], id = 3
Released [Thread-2], id = 2
进程2开始工作而他无法做到!!
答案 0 :(得分:3)
我认为你应该以相反的顺序释放锁。
答案 1 :(得分:1)
根据您的代码和输出,线程3可能会释放信号量3,因此正在等待它的线程2 - 获取它并在线程3完成之前打印消息。
我注意到你没有同步发布方法。
我强烈建议在获取和发布时使用synchronized块。
synchronized(this) {
available.get(id).acquire();
available.get(id+1).acquire();
}
synchronized(this) {
available.get(id).release();
available.get(id+1).release();
}
答案 2 :(得分:0)
您首先完成资源然后是线程,因此首先释放资源信号量。将释放方法替换为以下内容:
public void release(int id) {
resources.get(id + 1).release();
resources.get(id).release();
//resources.get(id + 1).release();
System.out.printf("Released [%s], id = %d\n", Thread.currentThread().getName(), id);
}