Lock Objects <译>

November 18, 2022 作者: yijianhao 分类: jdk文档翻译 浏览: 152 评论: 0

原文:https://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html

Synchronized code relies on a simple kind of reentrant lock. This kind of lock is easy to use, but has many limitations. More sophisticated locking idioms are supported by the java.util.concurrent.locks package. We won’t examine this package in detail, but instead will focus on its most basic interface, Lock.

Synchronized 代码依赖于一种简单的可重入锁,这类锁使用起来很简单,但有很多限制。java.util.concurrent.locks包支持更复杂的加锁习惯用法。我们不会解释详细介绍这个包,而是重点关注他最基本的Lock接口。

Lock objects work very much like the implicit locks used by synchronized code. As with implicit locks, only one thread can own a Lock object at a time. Lock objects also support a wait/notify mechanism, through their associated Condition objects.

Lock对象工作方式非常像使用了synchronized 代码的隐式锁。和隐式锁一样,一次只有一个线程可以拥有Lock对象。Lock对象也支持wait/notify机制,通过他们关联的Condition对象。

The biggest advantage of Lock objects over implicit 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 (if specified). The lockInterruptibly method backs out if another thread sends an interrupt before the lock is acquired.

与隐式锁相对,Lock对象最大的优势是它可以尝试获得锁后返回的能力。如果锁不可用,tryLock方法将会立即返回它或者在超时之前返回(如果指定)。如果另一个线程在获取锁之前发送中断,lockInterruptible方法将返回。(参考:Java中Lock,tryLock,lockInterruptibly有什么区别? - 知乎
https://www.zhihu.com/question/36771163

Let’s use Lock objects to solve the deadlock problem we saw in Liveness. 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. Here is the source code for the improved model, Safelock. To demonstrate the versatility of this idiom, we assume that Alphonse and Gaston are so infatuated with their newfound ability to bow safely that they can’t stop bowing to each other:

让我们来使用锁对象去解决我们在Liveness遇到的死锁问题。Alphonse和Gaston练习他们自己遇到朋友时如何鞠躬,我们通过要求我们的Friend对象在继续鞠躬之前必须为这两个参与者获得锁,来模拟这种改进。这里是改进模型的源代码,Safelock。

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 {
                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 (;;) {
                try {
                    Thread.sleep(random.nextInt(10));
                } 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();
    }
}

评论