多线程场景下synchronized方法执行逻辑与线程状态问询
嘿,针对你提出的这三个Java多线程问题,结合你给出的代码运行结果,我来逐个给你解释清楚:
问题1:当线程调用compute()方法时,是否能获取内部两个synchronized方法的访问权并执行自增操作?
当然可以。因为static synchronized方法的锁是类对象本身,而非实例对象。当一个线程调用add()方法时,它会获取该类的类锁,只要它持有这个锁,调用同一个类的其他static synchronized方法(比如addAgain())时,不需要重新竞争锁——因为锁已经在它手里了。所以线程进入compute()后,完全可以连续调用这两个同步方法并执行自增操作,不会被自己阻塞。
问题2:若线程进入for循环,会完成整个循环还是在竞争过程中切换给其他线程?
这没有绝对的答案,取决于JVM和操作系统的线程调度策略,但结合锁的特性来看:
当线程正在执行add()或addAgain()时,它持有类锁,其他线程根本无法进入任何static synchronized方法,只能等待。但当线程执行完一个同步方法(比如add())并释放类锁后,其他线程就有机会抢到锁,此时当前线程可能还没完成整个for循环就被切换。不过从你的运行结果来看,线程拿到锁后似乎能连续执行多轮操作,这只是调度器没有中途切换而已,并不是必然会完成整个循环——切换是完全可能发生的。
问题3:若发生线程切换,另一线程是否处于等待状态且不执行任何操作?
是的。当一个线程持有类锁时,另一个线程如果尝试调用add()或addAgain(),会立即进入阻塞等待状态,无法执行这两个同步方法里的任何代码。如果你的compute()方法里还有非同步的代码,那另一线程可以执行这部分,但在你的场景中compute()主要是调用这两个同步方法,所以当锁被占用时,它会卡在调用同步方法的位置,什么自增操作都做不了,直到持有锁的线程释放锁为止。
内容的提问来源于stack exchange,提问作者Arefe

