我有以下一段代码。它有两个对象,即 MultiThreadingTest 和 ThreadB 对象。当我们说synchronized(b)时,它到底是什么意思? “主”线程能否在 ThreadB 完成执行之前锁定 b?我无法理解同步块(synchronized block)中监视对象的意义。
package threads;
class MultiThreadingTest
{
public static void main(String[] args)
{
ThreadB b = new ThreadB();
b.setName("Thread B");
b.start();
synchronized(b)
{
System.out.println("Current thread : "+ Thread.currentThread().getName());
try
{
System.out.println("Waiting for b to complete...");
b.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("Total = "+b.total );
}
}
}
class ThreadB extends Thread
{
int total;
public void run()
{
synchronized(this)
{
System.out.println("Current thread : "+Thread.currentThread().getName());
for(int i=0;i<100;i++)
{
total = total + i;
}
notify();
}
}
}
最佳答案
把它想象成 child 的游戏,谁拿着 [whatever object] 就可以发言。谁持有监视器对象,谁就可以执行计算。
监视器是您要锁定的对象,在任何给定时间,只有一个线程访问每个监视器对象的同步块(synchronized block)保护的代码。对象本身是任意的,对同步没有太大影响(尽管您必须注意重新分配变量以及 null
引用)。此外,JB Nizet 在这里提出了关于在 Thread
对象上进行同步的一个很好的观点,因为许多内部 VM 方法都这样做,您可能会导致集市,难以检测错误和死锁。
进入锁定在不同监视器上的不同同步块(synchronized block)的两个线程将并发执行,类似于两组不同的人玩/执行“谁持有 xxx 就可以发言”游戏。锁定 this
只是一种无需创建额外的锁对象即可显示单个锁同步的便捷方式。
在您的情况下,ThreadB b
是从 ThreadB
类中指向的与 this
相同的对象,这意味着只有一个线程可以进入您定义的任何同步块(synchronized block)一次。该顺序高度依赖于哪个线程先运行、线程调度程序甚至底层系统。
监控对象的主要原因是为了实现复杂的线程安全机制。想象一个系统,其中每个同步块(synchronized block)都是单线程访问(即在任何时候,任何线程进入同步块(synchronized block)都会阻止整个 VM 中试图进入同步块(synchronized block)的所有其他线程)这不仅会导致性能大幅下降,还会只是没有意义。如果两个不相关的应用程序模块不共享数据且从不交互,为什么它们应该相互锁定?
当然,解决方案是让一个模块使用一个(或多个)监视器对象,这些对象与另一个模块不相关/不关联,因此两个模块可以彼此独立地同时执行(假设这是所需的行为)。
为了进一步说明,您可以这样写:
class MultiThreadingTest{
public static void main(String[] args){
ThreadB b = new ThreadB();
b.setName("Thread B");
b.start();
synchronized(b.lock){
System.out.println("Current thread : "+ Thread.currentThread().getName());
try{
System.out.println("Waiting for b to complete...");
b.lock.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total = " + b.total );
}
}
}
class ThreadB extends Thread{
public final Object lock = new Object();
int total;
public void run(){
synchronized(lock){
System.out.println("Current thread : "+Thread.currentThread().getName());
for(int i = 0; i < 100; i++){
total = total + i;
}
lock.notify();
}
}
}
与您使用的代码完全相同的效果(甚至更好,因为它解决了与 Thread.join() 和其他方法的冲突)。
关于java - 在与 'this' 实例不同的监视器上有一个同步块(synchronized block)是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30153362/