synchronized & producer & consumer & deadlock

 

Use synchronized to implement producers and consumers, and found that there is a deadlock, the code is as follows:

   (The wait notify nofityAll method can only be called on the monitor object (lock object)).

 

 

public class BlockingListBySync<E> implements BlockingList<E> {
    static final int MAXIMUM_CAPACITY = 1 << 30;
     int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }
    Object items[]= null;
    volatile  int count = 0;
    int putIndex = 0;
    int takeIndex = 0;
    public BlockingListBySync(int size){
        int realSize = tableSizeFor(size);
        items = new Object [realSize];
    }

    /**
     * Production object
     * @stop me
     * @throws InterruptedException
     */
    @Override
    public   void put(E e) throws InterruptedException{
        synchronized (this){
            while(count ==items.length){
                    this.wait();
            }
            putIndex ++;
            putIndex = putIndex & (items.length-1);
            items [putIndex] = e;
            count++;
           this.notify();
        }
    }

    public int size(){
        return count;
    }

    /**
     * consumer object
     * @return
     * @throws InterruptedException
     */
    @Override
    public E take() throws InterruptedException{
        synchronized (this){
            while(count ==0){

                this.wait();
            }
            takeIndex ++;
            takeIndex = takeIndex & (items.length-1);
            count--;
            E e = (E) items [takeIndex];

            items[takeIndex] = null;
            this.notify();
            return e;
        }
    }
}

   Multiple production threads call the put method.

 

  Multiple consumer threads call the take method.

   Running result: A deadlock occurs.

 

  Reason analysis: After the thread calls the wait() method, the thread enters the waiting queue of the monitor object, then there are both producer threads and consumer threads in the waiting queue. When the notify side of the monitor object is called, and a thread is arbitrarily selected from the waiting queue to wake up, the awakened thread may be a producer thread or a consumer thread. If the production thread wakes up the production thread, it is easy to deadlock.  

To put it simply: there are two kinds of threads in the waiting queue. The production thread wants to wake up the consumer thread, but the JVM selects the thread to wake up arbitrarily. If the production thread is awakened, it may enter a deadlock. 

 

Solution:

1. Replace nofity with notifyAll() 

      notifyAll() wakes up all the threads in the waiting queue on the monitor, which must include the consuming thread, so it can.

 

2. You can use ReentrantLock to create two Conditions (empty and full), which can distinguish thread types

 

 

 

 

 

              

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326529492&siteId=291194637