Waiting on a condition in a reentrant lock

前端 未结 3 859
無奈伤痛
無奈伤痛 2021-02-01 16:02

The following code is taken from the JavaDoc of Condition:

class BoundedBuffer {
  final Lock lock = new ReentrantLock();
  final Condition notFull  = lock.newCo         


        
相关标签:
3条回答
  • 2021-02-01 16:36

    I tested below code with single monitor and below always performs better - Tested on 2 core machine, Condition performance is 10-15% below on an average

     final Object sync = new Object();
      AtomicInteger add=new AtomicInteger();
      AtomicInteger remove=new AtomicInteger();
       final Object[] items = new Object[1];
       int putptr, takeptr, count;        
    
     public void add(Object x) throws InterruptedException {
           add.incrementAndGet();
    
         synchronized (sync) {
    
           while (count == items.length)
             sync.wait();
           items[putptr] = x;
           if (++putptr == items.length) putptr = 0;
           ++count;
           sync.notify();
            }
       }
    
       public Object remove() throws InterruptedException {
           remove.incrementAndGet();
    
         synchronized (sync) {
    
           while (count == 0)
             sync.wait();
           Object x = items[takeptr];
           if (++takeptr == items.length) takeptr = 0;
           --count;
           sync.notify();
           return x;
    
           }
       }
    
    
      public static void main(String[] args) {
        final BoundedBuffer bf=new BoundedBuffer();
    
        Thread put =new Thread(){
            public void run(){
            try {
                while(true)
                bf.add(new Object());
            } catch (InterruptedException e) {
    
            }
            }
    
        };
        put.start();
    
        Thread take= new Thread(){
            public void run(){
            try {
            while(true)
                bf.remove();
            } catch (InterruptedException e) {
    
            }
            }
    
        };
        take.start();
    
        try {
            Thread.sleep(1000L);
            put.interrupt();
            take.interrupt();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
    
        System.out.println("add:"+bf.add);
        System.out.println("remove:"+bf.remove);
    
    0 讨论(0)
  • 2021-02-01 16:37

    As far as re-entrancy, this means that a thread that holds a certain lock can re-acquire the same lock again. If this wasn't so, a synchronized method would not be able to call another synchronized method of the same object.

    Re-entrancy is not involved in the understanding of your problem.

    0 讨论(0)
  • 2021-02-01 16:51

    Both Lock and synchronized allow a thread to give up the lock when waiting and another thread can obtain the lock. To stop waiting, a thread have to re-acquire the lock.

    Note: They don't release it fully and if you take a stack trace you can have multiple threads which appear to be holding the lock at once, but at most one of them will be running (the rest will be blocking)

    From Condition.await()

    The lock associated with this Condition is atomically released and the current thread becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:

    • Some other thread invokes the signal() method for this Condition and the current thread happens to be chosen as the thread to be awakened; or
    • Some other thread invokes the signalAll() method for this Condition; or
    • Some other thread interrupts the current thread, and interruption of thread suspension is supported; or
    • A "spurious wakeup" occurs.

    In all cases, before this method can return the current thread must re-acquire the lock associated with this condition. When the thread returns it is guaranteed to hold this lock

    0 讨论(0)
提交回复
热议问题