繁体   English   中英

方法是否只进行同步,以便我们可以在以下代码中调用notifyAll()

[英]Are the methods get and put only synchronized so that we can call notifyAll() in the following code

我试图阅读Producer Consumer解决方案,我遇到了这段代码:

package SampleProjects;

public class ProducerConsumerTest {

    public static void main(String[] args) {
        CubbyHole c = new CubbyHole();
        Producer p1 = new Producer(c, 1);
        Consumer c1 = new Consumer(c, 1);
        p1.start();
        c1.start();
    }
}

class CubbyHole {

    private int contents;
    private boolean available = false;

    public synchronized int get() {
        while (available == false) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        available = false;
        notifyAll();
        return contents;
    }

    public synchronized void put(int value) {
        while (available == true) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        contents = value;
        available = true;
        notifyAll();
    }
}

class Consumer extends Thread {

    private final CubbyHole cubbyhole;
    private final int number;

    public Consumer(CubbyHole c, int number) {
        cubbyhole = c;
        this.number = number;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            int value = cubbyhole.get();
            System.out.println("Consumer #" + this.number + " got: " + value);
        }
    }
}

class Producer extends Thread {

    private final CubbyHole cubbyhole;
    private final int number;

    public Producer(CubbyHole c, int number) {
        cubbyhole = c;
        this.number = number;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            cubbyhole.put(i);
            System.out.println("Producer #" + this.number + " put: " + i);
            try {
                sleep((int) (Math.random() * 100));
            } catch (InterruptedException e) {
            }
        }
    }
}

在这段代码中,调用不同方法的线程,即生产者线程只关心put方法,而Consumer线程只关注get方法,所以我想知道为什么我们需要在内部循环检查内容时同步它们“同时,(可)”

然后我删除了synchronized关键字,它抛出了IllegalStateMonitor异常

所以我的问题是我们需要只有synchronized关键字,以便我们可以调用notifyAll()

因为notifyAllwait都要求调用线程拥有调用该方法的对象上的监视器。

抛出:

IllegalMonitorStateException - 如果当前线程不是此对象的监视器的所有者。

由于您正在调用notifyAllwait this ,因此您需要this对象的监视器。 synchronized实例方法为您提供。

对方法进行同步有几个影响:

  • 它允许wait和notifyAll通过让2个线程共享控制通知的监视器来工作。 在CubbyHole实例上调用notifyAll仅通知正在等待相同CubbyHole实例的线程。

  • 它为CubbyHole对象的实例成员建立内存可见性,这样一旦线程有监视器,就可以保证看到这些变量的当前值。 JVM可以积极地缓存值或重新排序指令,它依赖于像synchronized参数这样的标记,以了解它应该对这些优化施加什么限制。

对方法进行同步意味着线程需要获取调用该方法的实例的监视器才能开始执行该方法。 因此,cubbyhole对象上的put和get方法使用相同的监视器,如果一个线程正在执行其中一个方法,则阻止另一个线程进入另一个线程。 请注意,等待释放线程对锁定的保持(允许其他线程工作),等待线程必须重新获取监视器才能离开等待。

使用同步关键字,以便没有两个线程可以同时执行这些方法。 只允许一个线程访问put和get方法。 持有CubbyHole锁的线程将能够执行get和put方法。

如果您没有同步get和put,则会出现错误情况。 例如两种情况 -

  1. 如果可用== false并且两个生产者线程同时访问put方法。 假设线程1为内容分配10,线程2分配20并且可用== true。 那么消费者线程将获得10或20的价值?

  2. 如果可用== true且两个消费者线程同时访问get方法。 两者都将继续执行,因为get不同步,两者都会得到相同的值,这是错误的。

同步put方法的目的是只有一个生产者线程可以产生,而其他生产者线程应该等待,直到这个产生的值被一个消费者线程消耗。

同步get方法的目的是只有一个用户线程可以读取产生的值,而其他用户线程应该等待,然后通过设置为false来指示生产者产生。

暂无
暂无

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

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