C++ 如何使用pthreads以智能方式将变量共享给线程?
我想用智能线程使用p螺纹来同步C++中的线程。 我有一个全局变量:C++ 如何使用pthreads以智能方式将变量共享给线程?,c++,multithreading,pthreads,C++,Multithreading,Pthreads,我想用智能线程使用p螺纹来同步C++中的线程。 我有一个全局变量: int Resources = 0; 我有两个线程函数: void *incResources(void *arg) { while(1) { pthread_mutex_lock (&resourcesMutex); Resources += 2; pthread_mutex_unlock (&resourcesMutex); } pthread_exit((
int Resources = 0;
我有两个线程函数:
void *incResources(void *arg)
{
while(1)
{
pthread_mutex_lock (&resourcesMutex);
Resources += 2;
pthread_mutex_unlock (&resourcesMutex);
}
pthread_exit((void*) 0);
}
void *consumeResources(void *arg)
{
while(1)
{
pthread_mutex_lock (&resourcesMutex);
Resources--;
pthread_mutex_unlock (&resourcesMutex);
}
pthread_exit((void*) 0);
}
在main函数中,我初始化了两个消耗线程和一个递增线程:
pthread_mutex_init(&resourcesMutex, NULL);
pthread_create(&callThd[0], &attr, incResources, (void *)i);
pthread_create(&callThd[1], &attr, consumeResources, (void *)i);
pthread_create(&callThd[2], &attr, consumeResources, (void *)i);
我觉得这是不够的,可以做得更好。你能给我一些建议吗?我尝试使用“等待”,但我不明白:/
谢谢 >你寻找好的和C++的方式,我强烈建议阅读和离开pTrk使用期货和类似的高级事物。如果你一定要用手工摆线,你也可以找到很好的例子
您的问题陈述过于模糊,无法给出合理的建议——好线程的基本思想是根本没有共享状态,对于像您这样的握手情况,可能需要使用为此目的而设计的同步队列 一种更聪明的方法是使用
std::mutex
和std::thread
(或Boost等价物),这样就不需要手动解锁mutex
条件变量将允许使用者阻塞(不浪费CPU周期),直到有可用的工作:
struct Resource
{
int value;
std::mutex mx;
std::condition_variable cv;
};
void incResources(Resource& res)
{
while(1)
{
{
std::lock_guard<std::mutex> l(res.mx);
res.value += 2;
}
res.cv.notify_all();
}
}
void consumeResources(Resource& res)
{
while(1)
{
std::unique_lock<std::mutex> l(res.mx);
while (res.value == 0)
res.cv.wait(l);
res.value--;
}
}
我认为如果你使用C++,没有理由喜欢在p++上使用C++来代替C++ 11代码> STD::线程< /C>和STL同步类。
如果你不能使用C++ 11标准,你应该把PrPro本地接口包到合理的C++类表示(参见或实现)。
< P>看起来你正在试图实现一个生产者和消费者,++=线程创建工作(要减少的数字)和消费者拿走它们。 不要让消费者像那样处于一个琐碎的旋转循环中,而是看一看条件变量std::queue<Job*> queue;
pthread_mutex mutex;
pthread_cond cond;
void AddJob(Job* job) {
pthread_mutex_lock(&mutex);
queue.push_back(job);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
void* QueueWorker(void* /*threadInfo*/) {
Job* job = NULL;
for (;;) {
pthread_mutex_lock(&mutex);
while ( queue.empty() ) {
// unlock the mutex until the cond is signal()d or broadcast() to.
// if this call succeeds, we will have the mutex locked again on the other side.
pthread_cond_wait(&cond, &mutex);
}
// take the first task and then release the lock.
job = queue.pop();
pthread_mutex_unlock(&mutex);
if ( job != NULL )
job->Execute();
}
return NULL;
}
std::队列;
pthread_mutex mutex;
pthread_cond;
void AddJob(作业*作业){
pthread_mutex_lock(&mutex);
队列。推回(作业);
pthread_cond_信号(&cond);
pthread_mutex_unlock(&mutex);
}
void*QueueWorker(void*/*threadInfo*/){
Job*Job=NULL;
对于(;;){
pthread_mutex_lock(&mutex);
while(queue.empty()){
//解锁互斥锁,直到条件为signal()d或broadcast()to。
//如果调用成功,我们将在另一端再次锁定互斥锁。
pthread_cond_wait(&cond,&mutex);
}
//执行第一个任务,然后释放锁。
job=queue.pop();
pthread_mutex_unlock(&mutex);
如果(作业!=NULL)
作业->执行();
}
返回NULL;
}
这可以扩展到多个消费者
另一方面,虽然熟悉pthreads实现可能很有用,但您可能应该看看可用的线程包装器之一。C++11引入了std::thread和std::mutex,许多人都对boost信誓旦旦,但就我个人而言,我发现OpenSceneGraph团队的“OpenThreads”库是使用起来最简单、最优雅的库之一
编辑:这是一个完整的工作实现,尽管有一些人为的结束运行的机制
#include <queue>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int jobNo = 0;
class Job {
public:
Job() : m_i(++jobNo) { printf("Created job %d.\n", m_i); }
int m_i;
void Execute() { printf("Job %d executing.\n", m_i); usleep(500 * 1000); }
};
std::queue<Job*> queue;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void AddJob(Job* job) {
pthread_mutex_lock(&mutex);
queue.push(job);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
void* QueueWorker(void* /*threadInfo*/) {
Job* job = NULL;
for (;;) {
pthread_mutex_lock(&mutex);
while ( queue.empty() ) {
// unlock the mutex until the cond is signal()d or broadcast() to.
// if this call succeeds, we will have the mutex locked again on the other side.
pthread_cond_wait(&cond, &mutex);
}
// take the first task and then release the lock.
job = queue.front();
queue.pop();
pthread_mutex_unlock(&mutex);
if ( job == NULL ) {
// in this demonstration, NULL ends the run, so forward to any other threads.
AddJob(NULL);
break;
}
job->Execute();
delete job;
}
return NULL;
}
int main(int argc, const char* argv[]) {
pthread_t worker1, worker2;
pthread_create(&worker1, NULL, &QueueWorker, NULL);
pthread_create(&worker2, NULL, &QueueWorker, NULL);
srand(time(NULL));
// queue 5 jobs with delays.
for ( size_t i = 0; i < 5; ++i ) {
long delay = (rand() % 800) * 1000;
printf("Producer sleeping %fs\n", (float)delay / (1000*1000));
usleep(delay);
Job* job = new Job();
AddJob(job);
}
// 5 more without delays.
for ( size_t i = 0; i < 5; ++i ) {
AddJob(new Job);
}
// null to end the run.
AddJob(NULL);
printf("Done with jobs.\n");
pthread_join(worker1, NULL);
pthread_join(worker2, NULL);
return 0;
}
#包括
#包括
#包括
#包括
#包括
静态int-jobNo=0;
班级作业{
公众:
Job():m_i(++jobNo){printf(“已创建作业%d.\n”,m_i);}
国际货币基金组织;
void Execute(){printf(“作业%d正在执行。\n”,m_i);usleep(500*1000);}
};
std::队列;
pthread\u mutex\u t mutex=pthread\u mutex\u初始值设定项;
pthread_cond_t cond=pthread_cond_初始值设定项;
void AddJob(作业*作业){
pthread_mutex_lock(&mutex);
队列推送(作业);
pthread_cond_信号(&cond);
pthread_mutex_unlock(&mutex);
}
void*QueueWorker(void*/*threadInfo*/){
Job*Job=NULL;
对于(;;){
pthread_mutex_lock(&mutex);
while(queue.empty()){
//解锁互斥锁,直到条件为signal()d或broadcast()to。
//如果调用成功,我们将在另一端再次锁定互斥锁。
pthread_cond_wait(&cond,&mutex);
}
//执行第一个任务,然后释放锁。
job=queue.front();
queue.pop();
pthread_mutex_unlock(&mutex);
如果(作业==NULL){
//在本演示中,NULL结束运行,因此将转发到任何其他线程。
AddJob(空);
打破
}
作业->执行();
删除作业;
}
返回NULL;
}
int main(int argc,const char*argv[]{
pthread_t worker1,worker2;
pthread_create(&worker1,NULL,&QueueWorker,NULL);
pthread_create(&worker2,NULL,&QueueWorker,NULL);
srand(时间(空));
//排队等待5个有延迟的作业。
对于(尺寸i=0;i<5;++i){
长延迟=(rand()%800)*1000;
printf(“生产者睡眠%fs\n”,(浮动)延迟/(1000*1000));
usleep(延迟);
作业*作业=新作业();
AddJob(job);
}
//5个以上,没有延误。
对于(尺寸i=0;i<5;++i){
AddJob(新工作);
}
//null以结束运行。
AddJob(空);
printf(“已完成作业。\n”);
pthread_join(worker1,NULL);
pthread_join(worker2,NULL);
返回0;
}
您真正的问题是什么?我相信你不仅仅是在增加和减少一个变量。线程和效率更多地取决于消费者和生产者的问题/工作类型,而不仅仅取决于他们的数量。可能一比一的比例是有意义的。我们没有足够的信息来提供明智的见解。例:如果您所做的全部工作都是递增和递减一个int,那么您似乎有1个太多的使用者。:)我更喜欢使用类并将实例传递给线程函数,而不是使用一些全局引用。这看起来像是一个典型的生产者/消费者问题,通常使用队列
存储消息,使用互斥体/condition\u变量
对进行同步来解决。然而,正如@ChrisCM所说,我们没有足够的信息来giv
#include <queue>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int jobNo = 0;
class Job {
public:
Job() : m_i(++jobNo) { printf("Created job %d.\n", m_i); }
int m_i;
void Execute() { printf("Job %d executing.\n", m_i); usleep(500 * 1000); }
};
std::queue<Job*> queue;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void AddJob(Job* job) {
pthread_mutex_lock(&mutex);
queue.push(job);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
void* QueueWorker(void* /*threadInfo*/) {
Job* job = NULL;
for (;;) {
pthread_mutex_lock(&mutex);
while ( queue.empty() ) {
// unlock the mutex until the cond is signal()d or broadcast() to.
// if this call succeeds, we will have the mutex locked again on the other side.
pthread_cond_wait(&cond, &mutex);
}
// take the first task and then release the lock.
job = queue.front();
queue.pop();
pthread_mutex_unlock(&mutex);
if ( job == NULL ) {
// in this demonstration, NULL ends the run, so forward to any other threads.
AddJob(NULL);
break;
}
job->Execute();
delete job;
}
return NULL;
}
int main(int argc, const char* argv[]) {
pthread_t worker1, worker2;
pthread_create(&worker1, NULL, &QueueWorker, NULL);
pthread_create(&worker2, NULL, &QueueWorker, NULL);
srand(time(NULL));
// queue 5 jobs with delays.
for ( size_t i = 0; i < 5; ++i ) {
long delay = (rand() % 800) * 1000;
printf("Producer sleeping %fs\n", (float)delay / (1000*1000));
usleep(delay);
Job* job = new Job();
AddJob(job);
}
// 5 more without delays.
for ( size_t i = 0; i < 5; ++i ) {
AddJob(new Job);
}
// null to end the run.
AddJob(NULL);
printf("Done with jobs.\n");
pthread_join(worker1, NULL);
pthread_join(worker2, NULL);
return 0;
}