如何在 pthreads 中正确同步线程
How to properly synchronous threads in pthreads?
我正在使用pthreads和信号量实现生产者-消费者问题。我有 1 个生产者和 2 个消费者。我的生产者从文件中逐个读取字符,并将它们排队到循环队列中。我希望使用者从队列中读取并存储到单独的数组中。我希望读取方式是第一个使用者读取 2 个字符,第二个使用者每读取第 3 个字符。我正在尝试使用pthread_cond_wait()
执行此操作,但没有成功。这是我的代码:
#include<iostream>
#include<pthread.h>
#include<fstream>
#include<unistd.h>
#include<semaphore.h>
#include<queue>
#include "circular_queue"
// define queue size
#define QUEUE_SIZE 5
// declare and initialize semaphore and read/write counter
static sem_t mutex,queueEmptyMutex;
//static int counter = 0;
// Queue for saving characters
static Queue charQueue(QUEUE_SIZE);
//static std::queue<char> charQueue;
// indicator for end of file
static bool endOfFile = false;
// save arrays
static char consumerArray1[100];
static char consumerArray2[100];
static pthread_cond_t cond;
static pthread_mutex_t cond_mutex;
static bool thirdCharToRead = false;
void *Producer(void *ptr)
{
int i=0;
std::ifstream input("string.txt");
char temp;
while(input>>temp)
{
std::cout<<"reached here a"<<std::endl;
sem_wait(&mutex);
std::cout<<"reached here b"<<std::endl;
if(!charQueue.full())
{
charQueue.enQueue(temp);
}
sem_post(&queueEmptyMutex);
sem_post(&mutex);
i++;
sleep(4);
}
endOfFile = true;
sem_post(&queueEmptyMutex);
pthread_exit(NULL);
}
void *Consumer1(void *ptr)
{
int i = 0;
sem_wait(&queueEmptyMutex);
bool loopCond = endOfFile;
while(!loopCond)
{
std::cout<<"consumer 1 loop"<<std::endl;
if(endOfFile)
{
loopCond = charQueue.empty();
std::cout<<loopCond<<std::endl;
sem_post(&queueEmptyMutex);
}
sem_wait(&queueEmptyMutex);
sem_wait(&mutex);
if(!charQueue.empty())
{
consumerArray1[i] = charQueue.deQueue();
i++;
if(i%2==0)
{
pthread_mutex_lock(&cond_mutex);
std::cout<<"Signal cond. i = "<<i<<std::endl;
thirdCharToRead = true;
pthread_mutex_unlock(&cond_mutex);
pthread_cond_signal(&cond);
}
}
if(charQueue.empty()&&endOfFile)
{
sem_post(&mutex);
sem_post(&queueEmptyMutex);
break;
}
sem_post(&mutex);
sleep(2);
std::cout<<"consumer 1 loop end"<<std::endl;
}
consumerArray1[i] = ' ';
pthread_exit(NULL);
}
void *Consumer2(void *ptr)
{
int i = 0;
sem_wait(&queueEmptyMutex);
bool loopCond = endOfFile;
while(!loopCond)
{
std::cout<<"consumer 2 loop"<<std::endl;
if(endOfFile)
{
loopCond = charQueue.empty();
std::cout<<loopCond<<std::endl;
sem_post(&queueEmptyMutex);
}
sem_wait(&queueEmptyMutex);
sem_wait(&mutex);
if(!charQueue.empty())
{
pthread_mutex_lock(&cond_mutex);
while(!thirdCharToRead)
{
std::cout<<"Waiting for condition"<<std::endl;
pthread_cond_wait(&cond,&cond_mutex);
}
std::cout<<"Wait over"<<std::endl;
thirdCharToRead = false;
pthread_mutex_unlock(&cond_mutex);
consumerArray2[i] = charQueue.deQueue();
i++;
}
if(charQueue.empty()&& endOfFile)
{
sem_post(&mutex);
sem_post(&queueEmptyMutex);
break;
}
sem_post(&mutex);
std::cout<<"consumer 2 loop end"<<std::endl;
sleep(2);
}
consumerArray2[i] = ' ';
pthread_exit(NULL);
}
int main()
{
pthread_t thread[3];
sem_init(&mutex,0,1);
sem_init(&queueEmptyMutex,0,1);
pthread_mutex_init(&cond_mutex,NULL);
pthread_cond_init(&cond,NULL);
pthread_create(&thread[0],NULL,Producer,NULL);
int rc = pthread_create(&thread[1],NULL,Consumer1,NULL);
if(rc)
{
std::cout<<"Thread not created"<<std::endl;
}
pthread_create(&thread[2],NULL,Consumer2,NULL);
pthread_join(thread[0],NULL);pthread_join(thread[1],NULL);pthread_join(thread[2],NULL);
std::cout<<"First array: "<<consumerArray1<<std::endl;
std::cout<<"Second array: "<<consumerArray2<<std::endl;
sem_destroy(&mutex);
sem_destroy(&queueEmptyMutex);
pthread_exit(NULL);
}
我遇到的问题是在一次阅读后,消费者 2 在while(!thirdCharToRead)
中进入无限循环。有没有更好的方法来实现这一点?
好的,让我们从这段代码开始:
std::cout<<"Wait over"<<std::endl;
pthread_mutex_unlock(&cond_mutex);
thirdCharToRead = false;
此代码表示cond_mutex
不会保护thirdCharToRead
免受并发访问。为什么?因为它在不持有该互斥锁的情况下修改thirdCharToRead
。
现在看看这段代码:
pthread_mutex_lock(&cond_mutex);
while(!thirdCharToRead)
{
std::cout<<"Waiting for condition"<<std::endl;
pthread_cond_wait(&cond,&cond_mutex);
}
现在,while
循环检查thirdCharToRead
,因此我们必须在测试时保留任何锁来保护thirdCharToRead
免受并发访问。但是,如果thirdCharToRead
整个循环保持锁定状态,则while
循环将永远循环,因为没有其他线程可以更改它。因此,只有当我们在循环中的某个地方释放保护thirdCharToRead
的锁时,这段代码才有意义,而我们在循环中释放的唯一锁是在调用pthread_cond_wait
中cond_mutex
。
因此,只有在cond_mutex
保护thirdCharToRead
时,此代码才有意义。
休斯顿,我们有一个问题。一段代码说cond_mutex
不能保护thirdCharToRead
,一块代码说cond_mutex
保护thirdCharToRead
。
- 在C++中同步线程
- 将 10 个线程与原子布尔值同步
- 线程过程中的线程同步问题
- 如何定期同步线程?
- 同步线程安全的API,用于暴露缓存数据
- 如何在 pthreads 中正确同步线程
- 通过shared_ptr同步:线程清理器误报
- 如何同步线程以捕获相同数量的帧
- 同步线程和信号
- 使用条件变量(监视器)同步线程
- 同步线程创建和销毁(静态)对象
- NVIDA的CUDA"__syncthreads()"在传统C++中的等价物是什么。如何专业地同步线程?
- 使用事件同步线程
- 如何同步线程(消费者/生产者)
- 以最优雅的方式同步线程
- 使用互斥锁同步线程
- 计算着色器-如何全局同步线程
- GPU for loops:避免扭曲发散和隐式同步线程
- 如果已知访问顺序是安全的,如何在没有互斥锁的情况下同步线程/CPU
- Qt - 同步线程不起作用 - 线程停止但实际上不会停止,有时在不应该停止的时候停止