我是消息发布/消息泵架构的忠实粉丝。这是 MFC/Win32 提供的用于在线程之间传递数据的主要方法。这种架构是由线程消息驱动的事件,因此当接收线程正在处理线程消息时,它正在处理为线程之间的通信显式更新的数据(参见下面的示例)。
您可以自己实现这一点,并将锁定本地化到每个线程的单独线程消息列表。因此,当一个线程想要向另一个线程发送消息时,您大致执行以下操作
PostThreadMessage(msg, void* param, int paramSize)
{
lock(msgQueueLock);
// may wish to copy param
char paramCpy = malloc
msgQueue.Queue(msg, pparam, paramSize);
unlock(msgQueueLock);
}
那么任何线程的主循环就是
// thread's msg pump
while (1)
{
// can also use condition var to wait for queue to change...
lock(msgQueueLock);
HandleMsgLocally(msgQueue.Deque())
unlock(msgQueueLock);
}
无论如何,回到 MVC,如果您的模型发生变化,它可以发布到您的视图以更新特定字段,如下所示:
// Well known msg name
int msgName = MODEL_FIELD_A_UPDATED
...
void Model::UpdateFieldA(int newVal)
{
int* valToCommunicate = new int(newVal)
PostThreadMessage(MODEL_FIELD_A_UPDATED, valToCommunicate, sizeof(int))
}
...
void HandleMsgLocally(...void * param,)
{
if (msg == MODEL_FIELD_A_UPDATED)
{
int* val = reinterpret_cast<int*>(param);
//... process param
delete val;
}
}
优点是您可以本地化您的锁定。这是巨大的。此外,只要参数被发送者明确理解为新的并被接收者删除,您就不必担心访问共享内存。
这有很多缺点,延迟就是其中之一。如果您需要立即知道发生了什么变化,那么您需要实际制作共享数据并考虑最佳锁定方案。如果您确实需要一个可以随时从多个方向更新的全局状态,那么在我的书中这种情况下单例就可以了。这种设计真的最适合单向的数据,你可以进入竞争条件。但是,您也可以实现锁定 getter 以供一个线程从另一个线程进行检查,但要设置您必须发布的值。有很多变量需要考虑,但希望这可能对您有所帮助。此外,您可能会忘记删除消息中的参数。
更新基于编辑
根据您的信息,根据数据量,发布可以很好地工作。分析您的代码很重要。如果我是你,我会玩一些概念证明并切换到使用条件变量来管理同步性。如果您在 Windows 平台上,请务必使用他们的消息泵。