gpt4 book ai didi

java - 为什么线程释放锁后仍然运行?

转载 作者:太空宇宙 更新时间:2023-11-04 14:20:02 25 4
gpt4 key购买 nike

这是Oracle java教程中关于Lock对象的例子。请有人确认我是否正确解释了代码。

我只会考虑第一个线程,因为其他线程的工作方式相同。

首先,它获取alphonse的锁,并访问imendingBow方法。该方法现在尝试将两个实例的两个锁分配给线程。如果线程无法同时获取这两个锁,它将释放它获取的那一个。这就是我陷入困境的时候。如果线程释放锁,另一个线程可以访问这两个实例,并且第一个线程应该在释放锁后立即停止执行。但实际上并非如此。它仍然返回 boolean 值并继续运行bow方法中的else语句。为什么它可能发生?我认为就像同步代码一样,线程应该停止执行,直到再次获得锁。

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 (int n = 0; n <5;n++) {
try {
Thread.sleep(Math.round(Math.random()*1000));
} 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();
}
}

最佳答案

同步块(synchronized block)、Lock.lock()Lock.tryLock()Lock.tryLock(timeout) 之间存在细微差别.

仅当调用时该锁未被其他线程持有时,tryLock 方法才会获取锁。因此,当它无法获取锁时,它会立即返回。

lock 方法将一直等待,直到锁可用,同时等待该线程处于 hibernate 状态。使用synchronized 语句同步代码也是如此。该线程将等待,直到它可以获得该代码块的锁。

tryLock(timeout) 方法将一直等待,直到锁可用或超时为止。

javadoc 中或多或少有描述:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html

对于您期望的行为,您可以使用 lock 更改 tryLock 语句,您会发现线程最终会陷入死锁。

关于java - 为什么线程释放锁后仍然运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27299163/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com