在以下情况下,我应该如何控制对多个队列的多线程访问?

时间:2013-03-17 02:19:46

标签: c++ posix mutex semaphore condition-variable

我正在研究C ++中的多线程项目,该项目将数据发送到一系列网络连接。这是一些伪代码,用于说明正在发生的事情:

class NetworkManager
{
    Thread    writer;      // responsible for writing data in queues to the network
    Queue[]   outqueue;    // holds data until the network is ready to receive it
    Network[] nets;        // sockets or whatever
    Mutex[]   outlock;     // protects access to members of outqueue
    Mutex     managerlock; // protects access to all queues
    Condition notifier;    // blocks the write thread when there is no data
}

实际上它比这复杂得多,但我已经砍掉了很多不必要的细节。一个重要的细节是网络是速率限制的,并且程序独立于发送数据排队数据的能力是设计的一个特征(程序不必等待处理新数据,因为它在网络写入时阻塞)。

以下是该程序如何与此类进行交互的简要说明。请注意,QueueWriteToNetworkDoAdministrativeStuff在我的实现中由THE SAME外部线程管理。

QueueWriteToNetwork(network, data) // responsibility of external thread
    Let i = the index of the network to send to
    Lock(outlock[i])
    outqueue[i].Add(data)
    Unlock(outlock[i])
    Signal(notifier)

DoAdministrativeStuff(network, more) // responsibility of external thread
    Lock(managerlock)
    more.Process() // might do any of the following:
                   // connect or disconnect networks
                   // add or remove networks from list
                   // immediate write data to network, bypassing rate limiting
                   // other things that I forgot
    Unlock(managerlock)

WriterThreadMain() // responsibility of internal write thread
    Lock(managerlock)
    Loop forever:
        Check for data in every queue (locking and unlocking each queue)
        If all queues have no data to write:
            Wait(notifier, managerlock)
            continue
        If outqueue[i] has data ready to write
            Lock(outlock[i])
            Send data from outqueue[i]
            outqueue[i].Pop()
            Unlock(outqueue[i])

正如您可能会看到的,此方法存在一些问题(例如,如果使用QueueWriteToNetwork将写入队列到网络,因为WriterThreadMain正在检查队列是否为空,对Signal(notifier)的调用可能会被删除,即使有数据就绪,写队列仍可以等待。)

我需要用以下方式来表达这一点:

  • 向写入队列添加数据不会阻塞,也不会在相当短的时间内阻塞(具体而言,它不会在正在进行的网络写入期间阻塞)
  • DoAdministrativeStuff函数必须能够确保写入程序线程在安全状态下被阻止(即不访问任何队列,队列锁定或网络)

我已经探索了使用信号量跟踪写入队列中项目数的可能性。这将解决我之前提到的丢失更新问题。

最后,我的目标是Linux(使用Posix库提供类型pthread_tpthread_mutex_tpthread_cond_tsem_t),我不在乎关于与Windows的兼容性。另外,请不要推荐Boost。将任何Boost标头拉入我的代码会使编译耗费无法忍受。

0 个答案:

没有答案