C++ 持有多个线程

Posted

技术标签:

【中文标题】C++ 持有多个线程【英文标题】:C++ Holding a number of threads 【发布时间】:2013-08-14 17:48:54 【问题描述】:

我是 C++(在 Windows 上)和线程的新手,我目前正在尝试使用互斥锁、信号量和事件来解决我的问题。 我正在尝试使用构造函数和一个名为 Enter 的方法创建一个 Barrier 类。具有唯一方法 Enter 的类 Barrier 应该阻止任何进入它的线程,直到许多线程到达该方法。在构造器处等待它接收的线程数。 我的问题是如何使用锁来创造这种效果?我需要的是类似于反向信号量的东西,它可以保持线程直到达到计数,而不是像常规信号量那样让线程进入直到达到计数。 关于如何解决这个问题的任何想法都会很棒。 谢谢, 内塔内尔。

【问题讨论】:

你想使用c++11线程还是WinAPI? @dan - 我正在使用 WinAPI 【参考方案1】:

也许:

在ctor中,存储限制计数并创建一个空信号量。

当一个线程调用 Enter 时,首先锁定一个互斥体,这样你就可以安全地在里面旋转。将线程计数增加到限制计数。如果尚未达到限制,则释放互斥体并等待信号量。如果达到限制,则在循环中发出信号量 [limit-1] 次信号,将线程计数归零,(准备好下一次),释放互斥体并从 Enter() 返回。任何在信号量上等待并且现在准备好/正在运行的线程都应该从它们的“Enter”调用中返回。

互斥锁可防止任何已释放的循环“再次进入”线程,直到所有调用“Enter”并等待的线程都已设置为运行并重置屏障。

【讨论】:

我想过类似的事情。我的问题是互斥锁的释放和信号量的等待之间发生了什么。那时任何事情都可能发生,例如所需数量的线程来释放障碍,导致该线程等待下一组,即使它首先到达...... 我不确定您是否可以仅使用 Enter() 来实现您想要的。如果您还让每个线程在离开受保护区域(或即将返回)时调用 Leave() 函数,那么您可能可以构建一个两级屏障,它可以按照您的意愿工作。【参考方案2】:

你可以用条件变量来实现它。

这是一个例子:

我声明了 25 个线程并启动它们执行 WorkerThread 函数。

我检查阻塞/取消阻塞线程的条件是该部分中的线程数是否小于 2。 (我添加了一些断言来证明我的代码做了什么)。

我的代码只是在临界区休眠,并且在我减少临界区的线程数之后。

我还为 cout 添加了一个互斥锁以获取干净的消息。 #包括 #包括 #包括 #包括 #包括 #包括 #include /* 断言 */ 使用命名空间标准;

std::mutex m;
atomic<int> NumThreadsInCritialSection=0;
int MaxNumberThreadsInSection=2;
std::condition_variable cv;

mutex coutMutex;

 int WorkerThread()

    // Wait until main() sends data
    
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []return NumThreadsInCritialSection<MaxNumberThreadsInSection;);
    
    assert (NumThreadsInCritialSection<MaxNumberThreadsInSection);
    assert (NumThreadsInCritialSection>=0);
    NumThreadsInCritialSection++;
    
        std::unique_lock<std::mutex> lk(coutMutex);
        cout<<"NumThreadsInCritialSection= "<<NumThreadsInCritialSection<<endl;
    

    std::this_thread::sleep_for(std::chrono::seconds(5));
    NumThreadsInCritialSection--;
    
        std::unique_lock<std::mutex> lk(coutMutex);
        cout<<"NumThreadsInCritialSection= "<<NumThreadsInCritialSection<<endl;
    

    cv.notify_one();
    return 0;


int main()

    vector<thread> vWorkers;
    for (int i=0;i<25;++i)
    
        vWorkers.push_back(thread(WorkerThread));
    

    for (auto j=vWorkers.begin(); j!=vWorkers.end(); ++j)
    
        j->join();
    
    return 0;

希望对您有所帮助,如果您有任何问题,请告诉我,我可以评论或更改我的代码。

【讨论】:

【参考方案3】:

伪代码大纲可能如下所示:

void Enter()

    Increment counter (atomically or with mutex)
    if(counter >= desired_count)
    
        condition_met = true; (protected if bool writes aren't atomic on your architecture)
        cond_broadcast(blocking_cond_var);
    
    else
    
        Do a normal cond_wait loop-plus-predicate-check (waiting for the broadcast and checking condition_met each iteration to protect for spurious wakeups).
    

【讨论】:

以上是关于C++ 持有多个线程的主要内容,如果未能解决你的问题,请参考以下文章

Java并发编程:死锁(含代码)

具有多个线程的 c++ 服务器

Semaphore

死锁面试题

C++并发与多线程 4_创建多个线程数据共享问题分析

在 C++ 中,如何使用多个线程读取一个文件?