简体   繁体   English

Java和同步

[英]java and synchronization

I am preparing for the SCJP exam and I am having trouble with fully understanding synchronization. 我正在为SCJP考试做准备,但是在完全了解同步方面遇到了麻烦。 At line 6, I have read that the thread running in main needs a lock on 'b'. 在第6行,我读到main中运行的线程需要锁定'b'。 Why does it need a lock on this object? 为什么需要对此对象进行锁定? My understanding is that a synchronized block of code is a protected area that only one thread can be in at any time? 我的理解是,同步的代码块是一个受保护的区域,任何时间只能有一个线程进入? Moving on,the thread in main releases this lock and waits for the the thread in 'b to complete its run method. 继续前进,main中的线程释放此锁定,并等待'b中的线程完成其run方法。 The thread in 'b' is then meant to notify the thread in main that it has completed. 然后,“ b”中的线程将通知main中的线程已完成。 However, it does not look like it is notifying any specific thread here. 但是,它看起来并不像在这里通知任何特定线程。 This example is from the Sierra and Bates SCJP book. 此示例来自Sierra and Bates SCJP书。 Any light that can be shed on this would be grately appreciated. 对此,我们将不胜感激。 thanks 谢谢

class ThreadA {  
    public static void main(String [] args) {  
        ThreadB b = new ThreadB();  
        b.start();  

        **synchronized(b) {  //line 6**
            try {  
                System.out.println("Waiting for b to complete...");  
                b.wait();  
            } catch (InterruptedException e) {}  
                System.out.println("Total is: " + b.total);  
            }  
        }  
    }  
}

class ThreadB extends Thread {     
    int total;  

    public void run() {  
        System.out.println("K");  
        synchronized(this) {  
            for(int i=0;i<100;i++) {  
                total += i;  
            }  
            notify();  
        }  
    }  
}

Both threads synchronize on the same Object here, namely b . 这两个线程在同一个Object上同步,即b main() first aquires the lock, but then calls b.wait() , which releases the lock and waits for someone to call notify() on b . main()首先获取锁,然后调用b.wait() ,后者释放锁并等待有人在b上调用notify()

That means that when the run() method, which in this case is called on b , calls notify() , this will wake up the main() method again. 这意味着当在本例中在b调用的run()方法调用notify() ,这将再次唤醒main()方法。

So, that the lock is aquired on b isn't really important here, the important part is that both threads aquire the same lock, or the wait()/notify() cooperation won't work. 因此,在b上获得锁并不真正重要,重要的是两个线程都获得相同的锁,否则wait()/notify()合作将无法正常进行。

At line 6, I have read that the thread running in main needs a lock on 'b'. 在第6行,我读到main中运行的线程需要锁定'b'。 Why does it need a lock on this object? 为什么需要对此对象进行锁定?

Because that is what that line does. 因为那是那条线所做的。 It acquires that resource. 它获取该资源。 Other thread can get other synchronized block, but no other thread can acquire a lock on that object. 其他线程可以获取其他同步块,但是没有其他线程可以获取该对象的锁。

it does not look like it is notifying any specific thread here. 它似乎没有在这里通知任何特定的线程。

This is true. 这是真的。 The program has no idea which thread will be notify or even if any thread will be notified. 该程序不知道将通知哪个线程,甚至不通知任何线程。 You as the developer may conclude there is a particular thread which will be notified, perhaps because its the only thread wait()ing. 作为开发人员,您可能会得出结论,有一个特定的线程将被通知,这也许是因为它是唯一的线程wait()ing。

This is a very corner case and you would not do that. 这是一个非常极端的情况,您会这样做。
What happens is that main thread synchronizes on ThreadB object and wait . 发生的是main线程在ThreadB对象上同步并wait
When ThreadB finishes a notify is raised and as a result main is woken up and continues. ThreadB完成时,将引发一个notify ,结果main被唤醒并继续。
But this is not code you would normally write ie use Thread objects for synchronization . 但这不是您通常会编写的代码,即使用Thread对象进行synchronization
To see how corner case this is, just remove the notify from the loop of ThreadB . 要查看情况如何,只需从ThreadB循环中删除notify
The code will still work due to the fact you synchronize on a Thread object and the implementation raises a notify after a Thread has finished. 由于您在Thread对象上进行了同步,因此该代码仍然可以使用,并且在Thread完成后,该实现会引发一个通知。
The behavior is counter-intuitive and error-prone. 该行为是违反直觉的并且容易出错。

The code make use of wait() mechanism to ensure that result is computed by other ThreadB . 该代码利用wait()机制来确保result由其他ThreadB计算。

To wait on object you need to acquire lock on that object that is where line 6 , synchronized (b) comes in to picture. 要等待对象,您需要获取该对象的锁定,该对象位于line 6 ,其中已synchronized (b)进入图片。

Better way to execute same program is using Thread#join() method. 执行相同程序的更好方法是使用Thread#join()方法。

public final void join()
            throws InterruptedException

Waits for this thread to die.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM