Reentrantlock

A reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities. [1]

The advantage of using explicit locks is their ability to back out of an attempt to acquire a lock. The tryLock method backs out if the lock is not available immediately or before a timeout expires.

The following example is from [2]. Alphonse and Gaston have trained themselves to notice when a friend is about to bow. We model this improvement by requiring that our Friend objects must acquire locks for both participants before proceeding with the bow.

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.Random;
 
public class SafeLock
{
    static class Friend
    {
        private final String name;
 
        private final Lock lock = new ReentrantLock();
 
        public Friend(String name)
        {
            this.name = name;
        }
 
        public String getName()
        {
            return this.name;
        }
 
        public boolean impendingBow(Friend bower)
        {
            Boolean myLock = false;
            Boolean yourLock = false;
            try
            {
                /*
                 * The tryLock method backs out if the lock is not available
                 * immediately or before a timeout expires
                 */
                myLock = lock.tryLock();
                yourLock = bower.lock.tryLock();
            } finally
            {
                if (!(myLock && yourLock))
                {
                    if (myLock)
                    {
                        lock.unlock();
                    }
                    if (yourLock)
                    {
                        bower.lock.unlock();
                    }
                }
            }
            return myLock && yourLock;
        }
 
        public void bow(Friend bower)
        {
            if (impendingBow(bower))
            {
                try
                {
                    System.out.format("%s: %s has bowed to me!%n", this.name,
                            bower.getName());
                    bower.bowBack(this);
                } finally
                {
                    lock.unlock();
                    bower.lock.unlock();
                }
            } else
            {
                System.out.format("%s: %s started to bow to me, but"
                        + " saw that I was already bowing to him.%n",
                        this.name, bower.getName());
            }
        }
 
        public void bowBack(Friend bower)
        {
            System.out.format("%s: %s has bowed back to me!%n", this.name,
                    bower.getName());
        }
    }
 
    static class BowLoop implements Runnable
    {
        private Friend bower;
 
        private Friend bowee;
 
        public BowLoop(Friend bower, Friend bowee)
        {
            this.bower = bower;
            this.bowee = bowee;
        }
 
        public void run()
        {
            Random random = new Random();
            for (int i = 0; i<=10; ++i)
            {
                try
                {
                    Thread.sleep(random.nextInt(100)*20);
                } catch (InterruptedException e)
                {
                }
                bowee.bow(bower);
            }
        }
    }
 
    public static void main(String[] args)
    {
        final Friend alphonse = new Friend("Alphonse");
        final Friend gaston = new Friend("Gaston");
        new Thread(new BowLoop(alphonse, gaston)).start();
        new Thread(new BowLoop(gaston, alphonse)).start();
    }
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.