Java условия блокировки, кажется, не работают правильно - PullRequest
1 голос
/ 01 апреля 2020

У меня проблема, когда есть BoundedBuffer, а есть Consumers и Producers, производители заполняют буфер, а потребители удаляют из буфера.

Я использую потоки для Потребители и производители, и я пытался использовать условия блокировки, чтобы гарантировать, что буфер не заполнен для производителя и не пуст для потребителя.

К сожалению, это не работает так, как я хотел, кажется, что Потребитель / Производитель, когда они находятся в Condition.await, не позволяют другим потокам работать. Разве они не должны позволять им?

Вот мой код


class main
{
    public static void main (String[] args) throws InterruptedException
    {
        final int N = Integer.parseInt(args[0]); 
        BoundedBuffer teste = new BoundedBuffer(N);
        Thread c = new Consumidor(teste,N);
        Thread p = new Produtor(teste,N);
        c.start();
        p.start();
        c.join();
        p.join();
    }
}

class BoundedBuffer
{
    ArrayList<Integer> array;
    int index;
    int size;

    Lock l = new ReentrantLock();
    Condition notFull = l.newCondition();
    Condition notEmpty = l.newCondition();

    BoundedBuffer(int N)
    {
        this.array=new ArrayList<Integer>(N);
        this.index = 0;
        this.size=N;
    }

    public synchronized void put(int e) throws InterruptedException 
    {
        l.lock();
        try
        {
            while(this.index >= this.size)
            {
                notFull.await();
            }
            this.array.add(index,e);
            this.index++;
            notEmpty.signal();
        }
        finally
        {
            l.unlock();
        }       
    }

    public synchronized int get() throws InterruptedException 
    {
        int i;
        l.lock();
        try
        {   
            while(this.index <=0)
            {           
                notEmpty.await();
            }
            this.index--;
            notFull.signal();
            i = this.array.get(index);
        }
        finally
        {
            l.unlock();
        }
         return i;

    }
}

class Consumidor extends Thread
{
    private BoundedBuffer b;
    final int j;
    public Consumidor(BoundedBuffer b, int j)
    {
        this.b = b;
        this.j=j;
    }
    public void run() 
    { 
        int a;
        for (int i = 0; i < j ;++i)
        {  
            try
            {  
                a=b.get();
                System.out.println("GET: " +a); 
            }
            catch (Exception e) {}
        }
    }
}


class Produtor extends Thread
{
    private BoundedBuffer b;
    final int j;
    public Produtor(BoundedBuffer b, int j)
    {
        this.b = b;
        this.j=j;
    }
    public void run() 
    { 
        int a;
        for (int i = 0; i < j; ++i)
        {   
            try
            { 
                b.put(i);
                System.out.println("PUT: " +i);
            }
            catch (Exception e) {}
        }
    }
}

Заранее спасибо

1 Ответ

2 голосов
/ 02 апреля 2020

Не смешивайте внутренние блокировки c (что означает synchronized) с reentrantLocks. Этот код пытается получить блокировку intrinsi c, а затем повторную блокировку.

Для помещения synchronized в метод экземпляра требуется, чтобы поток, вызывающий метод, получил блокировку intrinsi c для экземпляра. ReentrantLock - это отдельная блокирующая конструкция, которая не использует это ключевое слово. Смешение двух механизмов не является необходимым и может привести только к проблемам.

(В частности, код вызывает await для объекта условия, в результате чего поток снимает блокировку повторного входа, но поток продолжает удерживать блокировку intrinsi c, не позволяя другому потоку войти в синхронизированный метод .)

Исправить это - удалить ключевое слово synchronized из вашего кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...