【问题标题】:Difference between synchronized(this) and few synchronized methods of classsynchronized(this) 与类的少数同步方法的区别
【发布时间】:2017-06-07 17:36:39
【问题描述】:

在 Programming Interviews Exposed 一书(Wrox 出版物)中,生产者消费者问题的代码对名为 IntBuffer 的类中的每个生产()和消费()方法都使用了“同步”关键字。这与在每个方法中使用 synchronized(this) 有什么不同吗?书中说,“当一个线程忙于在produce()中等待时,没有线程可以进入consume(),因为方法是同步的。”我觉得这对书中的代码没有意义,因为当一个线程忙于在produce()中等待时,没有线程可以进入produce()。然而,其他线程可以进入consume(),这打破了互斥的想法。生产和消费的方法应该完全同步吧?

书中代码:

public class IntBuffer
{
    private int index;
    private int[] buffer = new int[8];

    // Function called by producer thread
    public synchronized void produce(int num) {
        while(index == buffer.length - 1) {
            try { wait();}
            catch(InterruptedException ex) {}
        }
        buffer[index++] = num;
        notifyAll();
    }

    // Function called by consumer thread
    public synchronized int consume() {
        while(index == 0) {
            try { wait();}
            catch(InterruptedException ex) {}
        }
        int ret = buffer[--index];
        notifyAll();
        return ret;
    }
}

【问题讨论】:

标签: java synchronized


【解决方案1】:

不,它们是一样的。

private synchronized void foo() {}

private void foo2() {
 synchronized(this){
 }
}

它们的作用与监视调用它们的实例完全相同。

可以在 Jakob Jenkov 的博客中找到一个很好的教程 http://tutorials.jenkov.com/java-concurrency/synchronized.html#java-synchronized-example

编码愉快!

【讨论】:

  • 欢迎来到 Stack Overflow!我建议您删除答案的最后一行,使其更符合网站风格。 (如果每个人在修复错字时都添加了 EDIT 行,那么几乎每个答案都会有它们。)
【解决方案2】:

使用 synchronized(this) 要求调用线程获取与在方法上使用 synchronized 修饰符调用实例方法时相同的锁。生成的字节码存在一些差异,但这是一个非常低级的区别。

synchronized 关键字的目的是保护共享状态不被并发访问。生产和消费方法使用相同的内部状态,因此它们都受同一个锁保护是合理的。

发布的代码看起来做得很好,我唯一的挑剔是我会让方法抛出 InterruptedException 而不是捕获它。生产和消费方法都要求调用线程获取正在调用该方法的实例上的锁。

【讨论】:

    【解决方案3】:

    问:这与在每个方法中使用 synchronized(this) 有什么不同吗? 答:不,没有什么不同,通过使用 block (synchronize(this) 您可以只同步部分代码,而不是整个方法。 例如:

    public void m1(){
    // some code
    synchronized(this){ 
    // thread-safe code 
    }
    

    【讨论】:

    • 我想同时同步这两种方法,而不是单独同步。同步(this)不会满足我的目的,因为'this'是当前实例对吗? synchronize(this) 应该锁定整个实例,也就是说,produce() 和 consume() 中的一个方法一次会被一个线程处理。
    • synchronize(this) 将与同步实例方法完全相同,这与您现在所拥有的完全一样。您发布的代码是正确的,请在更改之前尝试理解它。请参阅 EJP 的答案。
    • 是的,是的。您需要在不同的对象上进行同步,或者您可能使用其他并发原语从生产者向供应者发出信号,反之亦然
    【解决方案4】:

    这与在每个方法中使用 synchronized(this) 有什么不同吗?

    没有。

    书上说,“当一个线程忙于在produce()中等待时,没有线程可以进入consume(),因为方法是同步的。”我觉得这对书中的代码没有意义,因为当一个线程忙于在produce()中等待时,没有线程可以进入produce()。但是其他线程可以进入consume(),这打破了互斥的想法。

    这是不正确的。两种方法都在同一个对象上同步,因此任何一种方法中都只能有一个线程,除非调用了wait(),它就是这样,它释放了锁。

    生产和消费的方法应该完全同步吧?

    是的,你说他们是。不清楚你在这里问什么。

    【讨论】:

    • 我同意“不清楚”部分,OP 发布的代码似乎是正确的。我只是强调wait() 释放了锁。这允许生产者内部的代码停止,消费者内部的代码重新启动,我认为这是 OP 可能误导自己的地方。
    猜你喜欢
    • 1970-01-01
    • 2012-02-21
    • 2011-05-22
    • 1970-01-01
    • 2012-02-03
    • 1970-01-01
    • 1970-01-01
    • 2015-07-25
    • 2011-03-31
    相关资源
    最近更新 更多