The Java Tutorials have been written for JDK 8.Java教程是为JDK 8编写的。Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.本页中描述的示例和实践没有利用后续版本中引入的改进,并且可能使用不再可用的技术。See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息,请参阅JDK发行说明。
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. java.util.concurrent.locks
包支持更复杂的锁定习惯用法。We won't examine this package in detail, but instead will focus on its most basic interface, 我们不会详细研究这个包,而是将重点放在它最基本的接口Lock
.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
对象。Lock
objects also support a 对象还通过其关联的wait/notify
mechanism, through their associated Condition
objects.Condition
对象支持wait/notify
机制。
The biggest advantage of 与隐式锁相比,Lock
objects over implicit locks is their ability to back out of an attempt to acquire a lock. Lock
对象的最大优点是能够从获取锁的尝试中退出。The 如果锁不立即可用或在超时过期(如果指定)之前不可用,tryLock
method backs out if the lock is not available immediately or before a timeout expires (if specified). tryLock
方法将退出。The 如果另一个线程在获取锁之前发送中断,则lockInterruptibly
method backs out if another thread sends an interrupt before the lock is acquired.lockInterruptbly
方法将退出。
Let's use 让我们使用Lock
objects to solve the deadlock problem we saw in Liveness. Lock
对象来解决我们在活性中看到的死锁问题。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. Friend
对象在继续使用鞠躬之前必须为两个参与者获取锁来模拟这种改进。Here is the source code for the improved model, 下面是改进模型Safelock
. 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:为了证明这个习语的多功能性,我们假设阿尔方斯和加斯顿对他们新发现的安全鞠躬的能力如此着迷,以至于他们无法停止相互鞠躬:
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(); } }