java oracle 教程中 Bow/Bower 示例与可重入锁的同步
Synchronisation of Bow/Bower example in java oracle tutorial with reentrant lock
这里给出的代码https://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html给出了bow和bower与锁对象的同步,这样就可以避免死锁。
这是代码
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();
}
}
我的问题是 - 据说线程 1 - alphanso 线程和线程 2 - gaston 线程始终以相同的速度执行。所以他们会一起调用 impendingBow() 。他们都试图获取自己和另一个对象的锁,如果任何锁不可用,那么他们释放获得的锁(如果有的话)。
现在,如果两个线程都以相同的速率执行行,那么 alphanso 线程将能够获得自身的锁,gaston 也将能够获得锁,但两者都无法获得其他线程的锁,因为它们已被自己获取。
现在根据代码,他们两个都将释放自己的锁(因为他们无法获得其他人的锁。)和 return false from impendingBow() 并且都将打印
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());
}
然后又是同样的事情。
这个过程不会 运行 无限期地没有人互相鞠躬吗?
Class BowLoop
具有随机延迟 (Thread.sleep(random.nextInt(10));
) 的无限循环,这会阻止您描述的情况。在 "collisions".
的情况下,在释放后重新尝试获取锁之前使用随机延迟是一种常见的做法
这里给出的代码https://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html给出了bow和bower与锁对象的同步,这样就可以避免死锁。
这是代码
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();
}
}
我的问题是 - 据说线程 1 - alphanso 线程和线程 2 - gaston 线程始终以相同的速度执行。所以他们会一起调用 impendingBow() 。他们都试图获取自己和另一个对象的锁,如果任何锁不可用,那么他们释放获得的锁(如果有的话)。 现在,如果两个线程都以相同的速率执行行,那么 alphanso 线程将能够获得自身的锁,gaston 也将能够获得锁,但两者都无法获得其他线程的锁,因为它们已被自己获取。 现在根据代码,他们两个都将释放自己的锁(因为他们无法获得其他人的锁。)和 return false from impendingBow() 并且都将打印
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());
}
然后又是同样的事情。 这个过程不会 运行 无限期地没有人互相鞠躬吗?
Class BowLoop
具有随机延迟 (Thread.sleep(random.nextInt(10));
) 的无限循环,这会阻止您描述的情况。在 "collisions".