在与实例不同的监视器上具有同步块'this'这意味着什么?



我有以下代码。它具有两个对象,即多刺林格 threadB 对象。当我们说同步(b)时,这是什么意思?"主"线程可以在螺纹b完成执行之前在b上锁定吗?我无法理解监视对象在同步块中的意义。

 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();
            }
        }
    }

将其视为孩子的游戏,谁持有[任何对象]会说话的人。持有监视器对象的任何人都可以在计算术语中执行。

监视器是您要锁定的对象,在任何给定时间,只有一个线程访问每个监视器对象保护的代码。该对象本身是任意的,并且对同步没有太多的重量(尽管您必须注意重新分配变量以及null参考)。另外,JB Nizet在同步Thread对象上提出了一个很好的观点,因为许多内部VM方法都可以引起Bazaar,难以检测错误和僵局。

在不同的监视器上锁定不同的同步块的两个线程将执行同时,类似于两个单独的人玩/颁布"曾经持有xxx的人会说话"游戏。锁定this只是表现出单个锁定同步而无需创建其他锁定对象的便捷方法。

在您的情况下,ThreadB b是从ThreadB类中指向this的对象,这意味着只有一个线程可以一次输入任何定义的同步块。该顺序高度依赖于哪个线程首先运行,线程调度程序甚至基础系统。

监视对象的主要原因是可以实现复杂的螺纹安全机制。想象一个系统,每个同步块都是单线程访问(即,在任何时候,任何线程进入同步块都会在整个VM中保存所有其他线程,试图输入一个同步块),这不仅会导致大规模的性能放缓,还会导致它只是没有意义。如果两个不相关的应用程序模块没有共享数据并且从不交互,为什么要互相锁定?

解决方案当然是要让一个模块使用与另一个模块无关/无关的一个(或几个)监视器对象,因此两者都可以同时执行彼此独立(假设这是所需的行为)。p>要进一步澄清,您可以写:

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();
        }
    }
}

to 恰好与您使用的代码相同(甚至更好,因为它可以解决与thread.join()和其他方法的冲突)。

synchronized(this)表示,如果另一个线程在代码块内部,该代码也无法输入该代码块,而该代码也与this引用的对象同步。

synchronized(b)表示,如果另一个线程在代码块内,该代码也无法输入该代码,该代码也同步在b引用的对象上。

因此,他们做了完全相同的事情。唯一的区别是用于锁定的对象。

请注意,等待,同步并在类型线程的对象上通知是一个真的很糟糕的主意。它使事物感到困惑,并会导致不必要的行为,因为其他方法(例如JOIN()也将线程用作监视器。

根据我的理解,不。运行()方法中的"此"对象和Main()方法中的" B"对象是相同的。

因此,在线程完成执行之前,"主"线程不可能获取锁。

在运行()方法中的notify()似乎在这种情况下似乎是多余的

ps:请四处寻找可能已经在论坛中提出的类似问题。他们可能有助于提供更多的理解。

最新更新