我的方案是拥有一个主线程和数十个工作线程。工作线程将处理来自不同端口的传入消息。
我想要做的是让主线程和工作线程共享一个相同的地图,工作线程将数据保存到地图中(在不同的存储桶中)。主线程定期grep地图内容。
代码如下:
struct cStruct
{
std::map<string::string> map1;
pthread_mutex_t mutex1;
pthread_mutex_t mutex2;
};
int main(){
struct cStruct cStruct1;
while (condition){
pthread_t th;
int th_rc=pthread_create(&th,NULL,&task,(void *) &cStruct1);
}
}
void* task(void* arg){
struct cStruct cs = * (struct cStruct*) arg;
while (coming data){
if (main_thread_work){
pthread_cond_wait(&count_cond, &cs.mutex1)
}
pthread_mutex_lock(&cs.mutex1);
// add a new bucket to the map
cs.map1(thread_identifier)=processed_value;
pthread_mutex_unlock(&cs.mutex1);
}
void* main_thread_task(void* arg){
sleep(sleep_time);
main_thread_work = true;
pthread_mutex_lock(&cs.mutex1);
// main_thread reads the std::map
main_thread_work = false;
pthread_cond_broadcast(&count_cond, &cs.mutex1)
pthread_mutex_unlock(&cs.mutex1);
}
我的问题是:
对于地图大小更改,我应该使用锁来保护地图。 但是对于具有某些密钥更新的地图,我可以让不同的线程同时修改地图吗? (假设不会同时访问两个相同的地图桶)
对于主线程greps地图,我想到使用条件等待来保存所有工作线程,而主线程正在掠过地图内容,然后做一个pthread_cond_broadcast来唤醒它。问题是,如果工作线程在主要开始工作时更新地图,则会有数据竞争。
请分享一些想法,以帮助我改进设计。
编辑1: 添加main_thread_task()。 我想避免的是工作线程到达pthread_cond_wait&#34;&#34; pthread_cond_broadcast并且逻辑出错。
所以我在主线程广播工作线程之前假为main_thread_work。
答案 0 :(得分:0)
您应该在每次访问地图时使用mutex
锁定机制(在您的情况下),而不仅仅是添加新的“#”桶。如果T1在T2插入新存储桶时尝试向映射写入某些值,则T1使用的指针/迭代器将变为无效。
关于pthread_cond_wait
。如果其他线程做的唯一事情就是修改地图,它可以完成这项工作。如果他们执行其他计算或处理一些非共享数据,最好使用相同的mutex
来保护对地图的访问,让其他线程完成他们的工作,这可能与共享地图无关。
答案 1 :(得分:0)
while (coming data){
if (main_thread_work){
pthread_cond_wait(&count_cond, &cs.mutex1)
}
pthread_mutex_lock(&cs.mutex1);
这显然是不对的。除非您持有保护它的锁,否则无法检查main_thread_work
。如何调用pthread_cond_wait
释放它不存在的锁?!
这应该是这样的:
void* task(void* arg){
struct cStruct cs = * (struct cStruct*) arg;
// Acquire the lock so we can check shared state
pthread_mutex_lock(&cs.mutex1);
// Wait until the shared state is what we need it to be
while (main_thread_work)
pthread_cond_wait(&count_cond, &cs.mutex1)
// Do whatever it is we're supposed to do when the
// shared state is in this state
cs.map1(thread_identifier)=processed_value;
// release the lock
pthread_mutex_unlock(&cs.mutex1);
}