不,同步不保证哪个Thread
先到达那里。In 只保证一次Thread
不能访问同步块。
把一个synchronized
街区想象成一个门上有锁的房间。我们不知道谁会先到门口,但一旦他们进去,他们就会进去锁上门。
其他人必须等到房间里的人准备好离开并解锁门。一旦发生这种情况,每个人都争先恐后地再次进入大门。
这完全取决于您设置Thread
关闭的顺序。但即便如此,也无法保证,因为 JVM 可能会随机地将Thread
s 和Thread
s挂起。yield
在类比中 - 带头到门口的人可能会被香蕉皮绊倒。不可能,但总是可能的。
如果您想获得保证,那么您需要wait
/ notify
- 以便读取线程检查flag
,如果是 ,则将false
自身暂停在一个循环中。
然后写入线程设置flag
并通知唤醒读取线程的锁监视器。
这是一个使用 Java 5 中的Lock
and Condition
api 的示例。我并不是说您必须使用它来优先于synchronized
and wait
/ notify
- 这只是我在周围使用的一个示例。
Reader
获取然后在循环中lock
检查标志。ready
如果标志是false
它await
的条件。这以原子方式释放lock
并暂停Thread
.
同时Writer
获取lock
并设置data
和ready
标志。然后它调用signalAll
并释放lock
.
这将唤醒Reader
然后读取ready
astrue
并继续执行print
语句。
输出将始终为42
(never -1
)。
public class App {
static volatile boolean ready = false;
static volatile int data = -1;
private static class Reader implements Runnable {
private final Lock lock;
private final Condition condition;
public Reader(Lock lock, Condition condition) {
this.lock = lock;
this.condition = condition;
}
@Override
public void run() {
lock.lock();
try {
while (!ready) {
try {
condition.await();
} catch (InterruptedException ex) {
//oh well
}
}
System.out.println(data);
} finally {
lock.unlock();
}
}
}
private static class Writer implements Runnable {
private final Lock lock;
private final Condition condition;
public Writer(Lock lock, Condition condition) {
this.lock = lock;
this.condition = condition;
}
@Override
public void run() {
lock.lock();
try {
data = 42;
ready = true;
condition.signalAll();
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
final ExecutorService executorService = Executors.newFixedThreadPool(2);
final Lock lock = new ReentrantLock();
final Condition condition = lock.newCondition();
executorService.execute(new Reader(lock, condition));
executorService.execute(new Writer(lock, condition));
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.DAYS);
}
}