说两个线程访问一个单例实例。两个线程正在访问名为doTask()
的相同函数。
public class MySingleton {
Object lock = new Object();
// I omit the constructor here.
public void doTask() {
//first non-synchronized code
synchronize(lock) {
//some heavy task
}
//final non-synchronized code
}
}
如果线程B正在执行繁重的任务,当线程A访问doTask()
时,我知道线程A 将运行//first non-synchronized code
,然后线程A 注意到主题B 获得了lock
,因此它无法运行同步//some heavy task
。但主题A 会跳过同步繁重任务继续运行//final non-synchronized code
还是主题A 等待锁定而不执行//final non-synchronized code
?
(我知道我可以尝试一下,但目前我没有适当的开发环境......)
答案 0 :(得分:2)
java中的synchronized
块强制线程等待它们获取对象的锁定。
它将等到B完成,然后锁定lock
的锁,并在块内运行代码,并继续执行另一端。
值得注意的是,当B完成执行some heavy task
的内容后,它将释放lock
上的锁定并在"同一时间运行final non-synchronized code
&#34 ; A运行同步块。
答案 1 :(得分:0)
当一个线程获取同步对象的监视器时,其余线程也将尝试获取它,此过程称为POLLING。因为所有剩余的线程都通过反复检查监视器锁定状态来尝试获取该对象的监视器。锁定被释放的那一刻它可以被任何线程获取。它实际上是由调度程序决定的。
答案 2 :(得分:0)
线程A将始终无限期地等待,直到线程B释放锁定。
在极端情况下,如果永远不会释放锁定,则线程A将永久停滞。
有时这很好,但通常你需要更好地控制事物,这就像ReentrantLock
之类的课程一样方便。
这可以执行synchronized
提供的所有操作,但也可以执行诸如检查锁是否已由当前线程拥有,尝试获取锁而不等待(如果锁已被另一个已经锁定则立即失败)之类的操作线程),或限制其等待一段时间。
请注意,虽然这些解决方案可用于控制互斥,但这不是它们唯一的功能,它们在可见性方面也起着重要作用。