当两个线程尝试访问同步块时会发生什么?
其中一个线程会在某处排队并稍后访问该线程,还是如果试用失败,该线程会放弃?
假设您的意思是同步块,一个线程将设法获取监视器,而另一个线程将阻塞直到监视器被释放。
有关详细信息,请参阅JLS 的第 14.19 节和第 17.1 节,包括:
同步语句(第 14.19 节)计算对对象的引用;然后它尝试在该对象的监视器上执行锁定操作,并且在锁定操作成功完成之前不会继续进行。执行完锁定操作后,将执行同步语句的主体。如果主体的执行完成,无论是正常的还是突然的,都会在同一个监视器上自动执行解锁操作。
(强调我的。)
如果您需要任何其他语义 - 例如超时 - 您应该使用java.util.concurrent.locks
包中的一种类型,以便您可以使用 和 等tryLock()
方法tryLock(long time, TimeUnit unit)
。
其中一个线程会在某处排队吗
是的,它在 JVM 中排队等待直到 runnig 线程释放锁。
如果试用失败,线程会放弃吗
不,它会一直尝试直到 JVM 还活着。但在另一个线程运行同步代码期间不尝试。(除非指定超时)
可以说ThreadA
并且ThreadB
正在尝试同步块sb
并ThreadB
成功。现在,ThreadA
将等到ThreadB
完成。同时,假设ThreadC
来了sb
。它看到该块正在由某个线程运行并在同一个队列中等待ThreadA
。当ThreadB
完成ThreadA
或ThreadC
有机会执行时。
因此,从技术上讲,它不是队列,而是类似的数据结构。
其中一个会在必要时永远等待(例如第一个线程执行无限循环),尽管那将是一个相当糟糕的设计。代码执行同步没有超时。
来自 JLS:
同步语句代表执行线程获取互斥锁,执行块,然后释放锁。当执行线程拥有锁时,没有其他线程可以获取锁。
如果synchronized
块正在由另一个线程执行,则两个线程都将等待。否则,将允许一个线程工作,而另一个线程将等待第一个线程完成其工作。