增强线程池和进程之间的互斥

Boost Mutex between threadpool and process

本文关键字:之间 进程 线程 增强      更新时间:2023-10-16

我在Test类中有4个函数:

void Test::A()
{
    boost::lock_guard<boost::mutex> lock(mutex);
    cout << "A!" << endl;
}
void Test::B()
{
    boost::lock_guard<boost::mutex> lock(mutex);
    cout << "B!" << endl;
}
void Test::C()
{
    boost::lock_guard<boost::mutex> lock(mutex);
    cout << "C!" << endl;
}
void Test::D()
{
    boost::lock_guard<boost::mutex> lock(mutex);
    cout << "D!" << endl;
}

如果我在循环中按字母顺序一次又一次地调用Test::ATest::D,并将它们绑定到boost thread_pool,那么在大多数情况下都可以正常工作。然而,有时,cout的声明会被打印出来。所以我可能会看到A B C D A B C C D A C D A D C。据我所知,这只与thread_pool何时获得新线程有关,我无法控制它们被调用的顺序。

我的问题是,我需要按顺序调用C()和D()(当需要调用它们时),而不关心A()和B()相对于彼此以及C(和D)的顺序。因此,我不再通过thread_pool调用C和D,而是通过主进程调用它,保留所有互斥对象。当我试图再次调用循环中的所有函数时,程序正好挂在C中的cout语句之前。我不明白为什么会这样。我可以在主进程和它的线程之间不使用互斥锁吗?

尽管这些函数的性质过于简单,但我无法将C和D的逻辑结合起来,因为这些函数最终将升级为基于事件的函数反复调用它们的循环只是模拟现实生活事件的虚拟循环。D总是在C之后被调用,但它可能被调用,也可能不被调用。

例如:

A B C D

A B C C D

A D

A B C C C

如果C和D可以由单独的事件触发(即,不能在同一线程中顺序调用它们),但D不能在C之前执行,则需要使用条件变量或其他同步方式(可能是信号量)。

由于您已经在使用boost,我建议您查看boost条件变量

这是完全正常的。当您启动两个线程池线程时,首先是A,然后是B,那么无法保证A在B之前到达cout语句。这只是可能。您创建的错误被称为"线程竞赛",这是使用线程的代码中非常常见的错误,而且众所周知很难诊断和修复。

这些线程以自己的速度运行。如果操作系统抢先A而不是B,例如,当它想允许另一个进程中的另一个线程运行时,那么B肯定会领先于A,首先到达cout语句。确保这些cout语句严格按顺序执行的唯一简单方法是使用一个线程。

如果您想维护执行顺序,请查看信号量。锁是FIFO,所以哪个线程先获得锁,就会先执行。为了确保在D之前调用C,请执行以下操作:

C : increment semaphore by 1
D : decrement semaphore by 1

如果信号量从0开始,D将只能在信号量为1时递减信号量(已经递增了C)。在这种情况下,您可以使用二进制信号量。可能的值为0或1。

如果有结果(可能是线程E),您可能有一个fifo队列来对C/D事件进行排序,并处理和删除该队列中的第一个元素。如果线程C和D可能相互干扰,则只制作一个线程CD。

如果C事件实际上触发了D事件,则可以考虑并行管道C->D。