【问题标题】:What is the need of synchronizing on a threadsafe object [duplicate]在线程安全对象上同步需要什么[重复]
【发布时间】:2014-09-27 14:36:41
【问题描述】:

我在网上搜索生产者消费者问题,我得到了this link。 程序员在这里为sharedqueue 使用了一个Vector

我想为什么我需要一个同步块,因为 Vector 已经是线程安全的。它必须自己处理线程。

但是当我试图通过删除同步块来做到这一点时。它给了我一个IllegalMonitorStateException。这是produce方法的代码sn-p

private void produce(int i) throws InterruptedException {

    //wait if queue is full
    while (sharedQueue.size() == SIZE) {
      //  synchronized (sharedQueue) {
            System.out.println("Queue is full " + Thread.currentThread().getName()
                                + " is waiting , size: " + sharedQueue.size());

            sharedQueue.wait();
      //  }
    }

    //producing element and notify consumers
   // synchronized (sharedQueue) {
        sharedQueue.add(i);
        sharedQueue.notifyAll();
   // }
}

我的问题是为什么我们需要对已经是线程安全的对象进行同步或锁定?

【问题讨论】:

  • 阅读 wait() 和 notify() 的文档:它清楚地表明您需要拥有锁才能调用这些方法。

标签: java multithreading vector thread-safety synchronized


【解决方案1】:

如果没有同步,你可以有这个:

Producer Thread              Consumer Thread                  
                             if (sharedQueue.isEmpty) {
sharedQueue.add(i);
sharedQueue.notifyAll();
                                  sharedQueue.wait()
                             }

因此,即使队列中有数据,消费者线程也可能永远等待,因为在它测试数据和开始等待有关添加数据的通知之间添加了东西。

当然有一些变通方法,例如wait 超时,但这些都有轮询开销、轮询间隔导致的延迟、丑陋的代码等等。当您可以使用同步时,没有理由诉诸此类事情。


那么为什么队列类是线程安全的还不够呢?好吧,线程安全类并不神奇!线程安全只是意味着对该类实例的单个方法调用是线程安全的。因此,例如,如果两个线程同时对同一个实例执行add,它不会破坏任何东西,也不会删除一个操作与另一个操作,或类似的事情。

但是,如果您有多个线程执行多个操作,那么它们可以交错,这就是多线程和抢占式多任务处理的全部意义所在!那么交错操作会发生什么,这取决于操作。例如,许多只执行add 的线程会以未指定的顺序添加内容,但这可能没问题。但是当您不希望操作以“随机”顺序发生时,您需要使用同步。

如上例所示,在这种情况下,“随机”顺序可能导致消费者无限期地等待,即使队列中有数据。事实上,如果你曾经有序列“做修改,通知服务员”,服务员做“看看有没有事要做,否则等待”,你有同样的问题,并且必须在修改通知和检查等待。


你会得到错误,因为Java在通知时要求你有锁,因为如上所述,没有锁没有意义,它总是一个错误,一个错误。这不是 Java 特有的,这是这种机制的基础,它们总是需要锁,在Wikipedia article section 阅读更多内容。

【讨论】:

  • 我知道我可以调整代码和所有内容,但我只想知道为什么我们需要锁定线程安全对象?正如您的编辑所说。 notify/wait 没有锁就没有意义, sharedqueue 是一个线程安全的对象。内部肯定已经有锁了
  • 添加了更多关于为什么拥有线程安全容器在这里没有帮助的文字。
  • 感谢海德的解释。谢谢你海德
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-23
  • 2016-11-14
  • 2015-06-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多