无法在Java中同步线程(使用信号量)

时间:2011-04-23 13:58:47

标签: java multithreading semaphore

美好的一天!

我遇到了同步线程的问题。我正在编写类似晚餐哲学家的程序。我有几个进程(例如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开始工作而他无法做到!!

3 个答案:

答案 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);
}