Java lock conditions seem to not be working right

Manuel0Borba :

I have a problem where there is a BoundedBuffer and there are Consumers and Producers, the producers fill the buffer and consumers remove from the buffer.

I'm using threads for the Consumers and Producers, and i was trying to use lock conditions to ensure that the buffer isn't full to the producer and isn't empty for the consumer.

Unfortunately it's not working the way I wanted, it seems that the Consumer/Producer, when they are in Condition.await, don't let the other threads work. Shouldn't they let them?

Here is my code


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) {}
        }
    }
}

Thanks in advance

Nathan Hughes :

Don’t mix intrinsic locks (meaning synchronized) with reentrantLocks. This code is trying to acquire the intrinsic lock and then the reentrantlock.

Putting synchronized on an instance method requires the thread calling the method to acquire the intrinsic lock on the instance. ReentrantLock is a separate locking construct that does not use that keyword. Mixing the two mechanisms is unnecessary and can only cause trouble.

(Specifically the code is calling await on the condition object, which causes the thread to release the reentrant lock, but the thread keeps holding onto the intrinsic lock, preventing the other thread from entering a synchronized method.)

The fix for this is to delete the synchronized keyword from your code.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=394416&siteId=1