TLDR;主要问题的版本:
在使用线程时,使用 1 个线程读取列表的内容是否安全,而另一个线程写入它,只要您不删除列表内容(重新组织顺序)并且仅在完全添加新对象后读取新对象
当一个线程正在将一个 Int 从“旧值”更新为“新值”时,是否存在风险,如果另一个线程读取此 Int,则返回的值既不是“旧值”也不是“新值”
如果线程忙,线程是否可以“跳过”关键区域,而不是仅仅进入睡眠并等待区域释放?
我有 2 段代码在单独的线程中运行,我想让一个充当另一个的生产者。我不希望任何一个线程在等待访问时“休眠”,而是如果另一个线程正在访问它,则在其内部代码中向前跳过。
我最初的计划是通过这种方法共享数据(一旦计数器足够高,就切换到辅助列表以避免溢出)。
我最初打算的流程伪代码。
Producer
{
Int counterProducer;
bufferedObject newlyProducedObject;
List <buffered_Object> objectsProducer;
while(true)
{
<Do stuff until a new product is created and added to newlyProducedObject>;
objectsProducer.add(newlyProducedObject_Object);
counterProducer++
}
}
Consumer
{
Int counterConsumer;
Producer objectProducer; (contains reference to Producer class)
List <buffered_Object> personalQueue
while(true)
<Do useful work, such as working on personal queue, and polish nails if no personal queue>
//get all outstanding requests and move to personal queue
while (counterConsumer < objectProducer.GetcounterProducer())
{
personalQueue.add(objectProducer.GetItem(counterconsumer+1));
counterConsumer++;
}
}
看到这里,乍一看一切都很好,我知道我不会从队列中检索半构建的产品,所以无论它在哪里,列表的状态都应该不是问题,即使线程切换时发生生产者正在添加一个新对象。这个假设是正确的,还是这里有问题?(我的猜测是消费者要求列表中的特定位置并将新对象添加到末尾,并且永远不会删除对象,这不会成为问题)
但引起我注意的是,如果“counterProducer”是“counterProducer++”,是否会出现类似的问题?这会导致临时值是“null”还是某个未知值?这会是一个潜在的问题吗?
我的目标是在等待互斥锁时不让两个线程锁定,而是继续它们的循环,这就是我首先制作上述内容的原因,因为没有锁定。
如果列表的使用会导致问题,我的解决方法是做一个链表实现,并在两个类之间共享,仍然使用计数器查看是否添加了新工作,并在personalQueue移动新时保留最后位置东西到个人队列。所以生产者添加新链接,消费者读取它们,并删除以前的链接。(列表上没有计数器,只是外部计数器知道添加和删除了多少)
避免counterConsumer++风险的替代伪代码(需要帮助)。
Producer
{
Int publicCounterProducer;
Int privateCounterProducer;
bufferedObject newlyProducedObject;
List <buffered_Object> objectsProducer;
while(true)
{
<Do stuff until a new product is created and added to newlyProducedObject>;
objectsProducer.add(newlyProducedObject_Object);
privateCounterProducer++
<Need Help: Some code that updates the publicCounterProducer to the privateCounterProducer if that variable is not
locked, else skips ahead, and the counter will get updated at next pass, at some point the consumer must be done reading stuff, and
new stuff is prepared already>
}
}
Consumer
{
Int counterConsumer;
Producer objectProducer; (contains reference to Producer class)
List <buffered_Object> personalQueue
while(true)
<Do useful work, such as working on personal queue, and polish nails if no personal queue>
//get all outstanding requests and move to personal queue
<Need Help: tries to read the publicProducerCounter and set readProducerCounter to this, else skips this code>
while (counterConsumer < readProducerCounter)
{
personalQueue.add(objectProducer.GetItem(counterconsumer+1));
counterConsumer++;
}
}
所以代码的第二部分的目标,我还没有弄清楚如何编写这个代码,是让两个类不要等待另一个类,以防另一个类处于更新 publicCounterProducer 的“关键区域”。如果我正确阅读了锁定功能,线程将进入睡眠状态等待释放,这不是我想要的。可能最终不得不使用它,在这种情况下,第一个伪代码会这样做,并且只是在获取值时设置一个“锁定”。
希望你能帮助我解决我的许多问题。