不,同步不保证哪个Thread先到达那里。In 只保证一次Thread不能访问同步块。
把一个synchronized街区想象成一个门上有锁的房间。我们不知道谁会先到门口,但一旦他们进去,他们就会进去锁上门。
其他人必须等到房间里的人准备好离开并解锁门。一旦发生这种情况,每个人都争先恐后地再次进入大门。
这完全取决于您设置Thread关闭的顺序。但即便如此,也无法保证,因为 JVM 可能会随机地将Threads 和Threads挂起。yield在类比中 - 带头到门口的人可能会被香蕉皮绊倒。不可能,但总是可能的。
如果您想获得保证,那么您需要wait/ notify- 以便读取线程检查flag,如果是 ,则将false自身暂停在一个循环中。
然后写入线程设置flag并通知唤醒读取线程的锁监视器。
这是一个使用 Java 5 中的Lockand Conditionapi 的示例。我并不是说您必须使用它来优先于synchronizedand wait/ notify- 这只是我在周围使用的一个示例。
Reader获取然后在循环中lock检查标志。ready如果标志是false它await的条件。这以原子方式释放lock并暂停Thread.
同时Writer获取lock并设置data和ready标志。然后它调用signalAll并释放lock.
这将唤醒Reader然后读取readyastrue并继续执行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);
}
}