Java 生产者/消费者使用信号量。消费者得到的是尾部,而不是队列的头部

Java 生产者/消费者使用信号量。消费者得到的是尾部,而不是队列的头部,java,multithreading,queue,producer-consumer,Java,Multithreading,Queue,Producer Consumer,正如标题所示,这是一个使用信号量的生产者/消费者实现 没有死锁问题,但似乎每当消费者想要删除队列中的下一个项目时,它总是尾部 伪代码: class Consumer { while (!q.isEmpty() || !dataRead()) { empty.acquire(); mutex.acquire(); queue.remove(); mutex.release(); full.release();

正如标题所示,这是一个使用信号量的生产者/消费者实现

没有死锁问题,但似乎每当消费者想要删除队列中的下一个项目时,它总是尾部

伪代码:

class Consumer {
    while (!q.isEmpty() || !dataRead())
    {
       empty.acquire();
       mutex.acquire();
       queue.remove();
       mutex.release();
       full.release();
    }

    synchronized (caller)
    {
         caller.dataWritten = true;
         caller.notify();
    }
}

class Producer {
    for (int i=0; i < 100; i++)
    {
       full.acquire();
       mutex.acquire();
       queue.add(i);
       mutex.release();
       empty.release();
    }
    ...also notify Consumer that we're done...
}

class MainThread {
 ...
 new Thread(new Producer(args)).start();
 new Thread(new Consumer(args)).start();

 synchronized (this) {
    while (!dataWritten())
      wait();
 ...
 }
输出如下所示:

已生成项0…值为0。 第1项产生……价值1。 项目0已消耗…值1。 项目1已消耗…值1。 显然,当我移除头部时,我希望移除的顺序与FIFO相同

我正在使用ConcurrentLinkedQueue实现,但已经尝试了许多其他实现,如LinkedList、BlockingQueue实现等

此外,我还尝试在队列对象上进行同步,并在ditch工作中使变量变为volatile,但这并没有产生任何影响

我认为这与对队列的陈旧引用有关,但是已经没有办法尝试了

编辑:输出的错误在于,当使用项0时,它应该使用值0,而不是1,因为这是为项0生成的值

我似乎无法用最少的代码复制


看起来,如果数据来自一个迭代器,该迭代器只需花费少量的时间来读取信息,那么输出就像我的示例中那样是关闭的,但是如果我只是插入一些常量值,那么输出是正确的。既然只有一个制作人,为什么会有不同呢?

我不确定我是否正确解释了您程序的输出。我假设项目x指的是在生产者的for循环中递增的整数。如何设置值字段的值


由于您首先将项目0添加到队列中,并且项目0是您第一次使用的项目,因此队列的行为在我看来似乎是正确的。

为什么要给我们PSEDOO代码?给我们一个相反的答案。为什么在消费者中你得到的是空的,但释放的是满的?此外,如果您使用的是ConcurrentLinkedQueue,那么为什么要使用信号量?很可能代码中存在错误,但如果没有我们可以运行的自包含示例,则无法说出位置。@Duncan/Peter我将发布到MCVE的链接@如果你需要一个关于信号量如何工作的参考,你可以在维基百科上查看基本信号量的使用。empty.acquire检查缓冲区中是否有空间,full.release让生产者知道有空间…等等。因此,为了验证,在保证互斥的情况下跨多个线程使用任何队列实现没有明显的错误?输出表示消耗的第一个项的值为1,而实际情况并非如此。项0的值为0。