我有一个简单生产者/消费者情形,其中仅存在曾经正在生产中的单个项目/消耗。此外,制片人,然后再继续等待工作者线程结束。我知道那种避免了多线程的整点,但请你只认为它真正需要的是这样的(:

此代码不能编译,但我希望你的想法:

// m_data is initially null

// This could be called by any number of producer threads simultaneously
void SetData(object foo)
{
    lock(x)                      // Line A
    {
        assert(m_data == null);
        m_data = foo;
        Monitor.Pulse(x)         // Line B
        while(m_data != null)
            Monitor.Wait(x)      // Line C
    }
}

// This is only ever called by a single worker thread
void UseData()
{
    lock(x)                      // Line D
    {
        while(m_data == null)
            Monitor.Wait(x)      // Line E
        // here, do something with m_data
        m_data = null;
        Monitor.Pulse(x)         // Line F
    }
}

这里的情况,我不知道:

假设许多线程调用的SetData()与不同的输入。 只有其中一人将获得锁内,其余的将被封锁(A线) 假设一个锁套的 M_DATA 内得到并使得其对C线的方式。

问题:无法对C线的等待()允许在A线另一个线程来获得锁和重写的 M_DATA 前的工作线程甚至到达它

假设不会发生,且工作线程处理原始的 M_DATA ,并最终使得其方式线f,当脉冲()熄灭发生了什么?

只能在C线线程等待能够获得锁?还是会与所有其他线程A线的等待也可以竞争?

基本上,我想知道如果脉冲()/等待()相互专门“发动机罩下”进行通信,或者如果他们是在与锁相同的水平()。

到这些问题的解决,如果它们存在,是显而易见的当然 - 只是环绕的SetData()与另一个锁定 - 比如,锁(Y)。 我只是好奇,如果它甚至开始有问题。

有帮助吗?

解决方案

有没有保证,消费者将之前另一位制片人等待或就绪队列排队。结果 C#和Java风格监视器上维基百科描述的,“隐式状态监视器” 点击 在Monitor会发生什么很好的概述(摘自优秀的网站): “替代文字”

  

“可以在C线的等待()允许在A线另一个线程以获得工作线程甚至到达之前锁定和重写M_DATA?”

假设SetData()由两个生产者线程,的 P1 &的 P2 叫。结果 消费者螺纹,的 C1 开始为好。结果, 的 P1 ,<强> P2 和<强> C1 所有进入就绪队列。结果 的 P1 首先获取锁。结果 等待队列为空,在Pulse() line B没有效果。结果 的 P1上line C 等待,因此它被放置在等待队列。结果 在就绪队列中的下一个线程获取锁。结果 它同样可以是的 P2 C1 - 在第一种情况下,则断言失败结果。 你有一个竞争条件。

  

“假设不会发生,且工作线程处理原始M_DATA,并最终使其以线f方式,当脉冲()熄灭,会发生什么?”

它将从等待队列就绪队列移动服务员。结果 该锁由线程认为问题Pulse()。结果 该通知线程的有机会的脉动线程释放后获取锁锁(有可能已经是别人就绪队列)。结果 从 MSDN,监视器.Pulse():点击 “当前拥有指定的对象的锁的线程调用此方法,以信号通知所述下一个线程在线路的锁。在接收到脉冲,等待线程移动到就绪队列,当线程调用的脉冲释放锁,在就绪队列中的下一个线程(其不一定是呈脉冲式的线程)获取锁“。

  

“只会线程等待C线能够获得锁?还是会与所有其他线程A线的等待也可以竞争?”

所有线程都在具有下一个锁的就绪队列“竞争”。结果, 不要紧,如果他们到达那里的直链或从等待队列通过Pulse()的手段。

<子>的“队列”可能被通过其它手段来实现。 (不是队列数据结构本身)。结果 这样一Monitor实现可能无法保证公平性 - 但可能具有更高的总体生产能力/性能。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top