Реализация семафоров с использованием концепции монитора - PullRequest
3 голосов
/ 08 марта 2012

Я пытаюсь реализовать семафоры, используя концепцию монитора в Java.Т.е. класс Java, который реализует слабый счетный семафор (используя методы init, signal и wait)

Может кто-нибудь сказать мне, корректен ли этот класс (если нет, в чем проблема):

class MyMonitor
{
    int counter = 0;

    //init
    public MyMonitor( int init )
    {
        counter = init;
    }

    //Signal
    public synchronized void S()
    {
        counter++;
        notify();
    }

    //Wait
    public synchronized void W()
    {
        if( counter == 0 )
        {
            try
            {
                wait();
            }
            catch(InterruptedException e) { }
        }

        counter--;
    }
}

Если это правильно, кто-нибудь может дать мне представление о том, как я могу проверить класс.

Ответы [ 3 ]

1 голос
/ 18 сентября 2012

Должно быть так (с while, а не if):

class YourMonitor
{
    int counter = 0;

    //init
    public MyMonitor( int init )
    {
        counter = init;
    }

    //Signal
    public synchronized void S()
    {
        counter++;
        notifyAll();
    }

    //Wait
    public synchronized void W()  throws InterruptedException
    {
        while ( counter <= 0 )
        {
            wait();
        }

        counter--;
    }
}

Как проверить:

public class TestYourSemaphore
{
    private static final int CNT = 100000;

    private int x = 0;
    private YourSemaphore s = new YourSemaphore();

    public void run() throws InterruptedException
    {
        Thread t1 = new Thread(new MyRunnable());
        Thread t2 = new Thread(new MyRunnable());
        Thread t2 = new Thread(new MyRunnable());

        t1.start();
        t2.start();
        t3.start();

        t1.join();
        t2.join();
        t3.join();


        // Verify, that the X has correct value
        if (x != 3 * CNT)
        {
            throw new RuntimeException("Race condition error!");
        }
        System.out.println("Finished");
    }

    private class MyRunnable implements Runnable
    {
        @Override
        public void run()
        {
            for (int i = 0; i < CNT; i++)
            {
                //un-comment to use Semaphores
                //s.enter();
                x = x + 1;
                //s.leave();
            }
        }
    }
}
  • Без семафора Исключение генерируется постоянно (почти).
  • При использовании предложенного семафора исключение не генерируется.
  • С вашим семафором иногда создается исключение (но не так часто, как без семафоров).

Проблема с вашим семафором:

  1. резьба 1 имеет блокировку
  2. нить 2 и нить 3 wait() ing
  3. поток 1 звонков notifyAll()
  4. поток 2 и 3 одновременно входят в критическую секцию, что плохо:)
0 голосов
/ 20 марта 2012

Просто вопрос: почему вы не используете стандарт Java?http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html?

0 голосов
/ 08 марта 2012

Ну, единственная проблема, которую я вижу, это эта часть:

    if( counter == 0 )
    {
        try
        {
            wait();
        }
        catch(InterruptedException e) { }
    }

    counter--;

Если поток прерывается во время ожидания, он просто выйдет из оператора if, уменьшит счетчик ниже 0, а затем ваша семафорная система пойдет ужасно неправильно, поскольку теперь никто не будет вынужден ждать, потому что counter меньше 0.

Вам, вероятно, следует заменить if на while, на всякий случай.

...