2014-09-27 92 views
-2

我在网上搜索一个生产者消费者问题和我有this link上同步的需要。 程序员使用矢量这里的sharedqueue什么是线程安全的对象

我想为什么我需要一个同步块作为向量已经线程安全。它必须自己处理线程。

但是当我试图通过移除synchronized块做到这一点。它给了我一个IllegalMonitorStateException。以下是代码片段生产方法

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

我的问题是,为什么我们需要一个已经线程对象上同步或采取锁?

+0

阅读wait()和notify()的文档:它清楚地表明您需要有锁才能调用这些方法。 – 2014-09-27 14:39:21

回答

2

Wihtout同步,你可以有这样的:

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

所以,尽管有数据在队列中,消费者线程将等待可能永远,因为它之间添加的东西得到的测试数据,并开始等待有关添加数据的通知。

当然,还有一些解决方法,比如wait上的超时,但是这些都有轮询开销,由于轮询间隔引起的延迟,难看的代码等等。当你可以使用同步时,没有理由诉诸此类事情。


那么,为什么它是不够的,队列类是线程安全的?那么,线程安全的课程并不神奇!线程安全意味着,对该类实例的单个方法调用是线程安全的。因此,例如,如果两个线程在同一时间,以同一实例做add,它不会破坏任何东西,消除与其他或类似的东西一个操作。

但是,如果你有多个线程执行多个操作,那么他们可以交错,这是许多线程和抢先式多任务毕竟整点!那么交错操作会发生什么,这取决于操作。例如,只有add的许多线程会以某种未指定的顺序添加内容,但这可能是正确的。但是,如果您不希望操作以“随机”顺序发生,则需要使用同步。

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


,你会得到错误,因为Java要求你通知的时候,因为上面解释的,它使无锁没有意义的有锁,这将永远是一个错误,一个错误。这是不是Java具体,这是这类机制的根本,他们总是需要的锁,在这个Wikipedia article section阅读更多。

+0

我知道我可以调整代码和所有,但我想知道为什么我们需要锁定一个线程安全的对象?正如你的编辑所说。 **通知/等待没有锁定没有意义,**共享队列是一个线程安全的对象。内部必须已经有一个锁定 – gusainhimanshu 2014-09-27 14:52:11

+0

增加了一些关于为什么有一个线程安全的容器在这里没有帮助的文字。 – hyde 2014-09-27 15:06:01

+0

感谢hyde的解释。谢谢海德 – gusainhimanshu 2014-09-28 20:44:00

相关问题