我正在尝试构建多线程客户端-服务器项目,其中:每个客户端在两个队列中插入姓名和姓氏,一个用于姓名,另一个用于姓氏。插入后,我创建 N 个工作线程以查找 2 个队列之间的匹配项。如果找到匹配项(姓名 == 姓氏),则线程必须删除两个队列中匹配的节点。
我在考虑两种可能的同步方案:
一个线程正在工作,N-1 个线程被挂起,以便在删除匹配节点后更新队列。但我认为它效率低下,因为我没有并行线程执行。
2 个线程只更新队列,N-2 个线程只同时读取队列,我只锁定正在读取或删除的节点。
第二个场景的执行如下,但我对嵌套锁感到困惑。
以下代码用于服务器。客户端只在队列中插入名称。
updateOne线程一直在等待,直到条件变量update变为1。如果为1,则删除匹配的节点并转为条件变量update到 0 并释放 func 线程。
对于所需的同步场景,我需要两件事:
问题 1:**我怎样才能让其余的 func 线程正常工作而不被挂起? ** 2) updateOne 线程可以获取reader 锁以遍历队列并删除匹配的节点,而func 线程读取其余节点
问题 2:如何使用 readerLock 来锁定节点级别而不是队列级别?
问题 3:pop_from_index 是否正常工作?
#include "list.h"
typedef struct info {
node *info_buy;
node *info_sell;
}info;
int update = 0;
int matches = 0;
pthread_mutex_t reader_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t update_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition = PTHREAD_COND_INITIALIZER;
void *updateOne (void *args){
info *arg = (info *)args;
node *temp_buy = arg->info_buy;
node *temp_sell = arg->info_sell;
printf("waiting\n");
while (1){
pthread_mutex_lock(&update_lock);
while (update != 1){
pthread_cond_wait(&condition, &update_lock);
}
printf("woke up\n");
node *tb = temp_buy;
node *ts = temp_sell;
int index_to_delete = -1;
while (tb != NULL){
if (tb->valid == 0){
index_to_delete = tb->n;
printf("Index buy %d\n", tb->n);
pop_from_index(&temp_buy, index_to_delete);
}
tb = tb->next;
}
printList(temp_buy);
while (ts != NULL){
if (ts->valid == 0){
index_to_delete = ts->n;
printf("Index sell %d\n", ts->n);
pop_from_index(&temp_sell, index_to_delete);
}
ts = ts->next;
}
printList(temp_sell);
update = 0;
pthread_cond_broadcast(&condition);
pthread_mutex_unlock(&update_lock);
}
return NULL;
}
void *func(void *args)
{
// Store the value argument passed to this thread
/*info *n = (info*) args;
pthread_mutex_lock(&reader_lock);
int index = -1;
node *t1 = n->info_buy;
while (t1 != NULL){
node *t2 = n->info_sell;
while (t2 != NULL){
if (strcmp(t1->command, t2->command) == 0){
pthread_mutex_lock(&update_lock);
update = 1;
pthread_cond_broadcast(&condition);
t1->valid = 1;
t2->valid = 1;
pthread_mutex_unlock(&update_lock);
break;
}
t2 = t2->next;
}
t1 = t1->next;
}
pthread_mutex_unlock(&reader_lock);
*/
info *queues = (info *) args;
node *buy = queues->info_buy;
node *sell = queues->info_sell;
while (1){
pthread_mutex_lock(&reader_lock);
node *tb = buy;
while (tb != NULL){
node *ts = sell;
while (ts != NULL){
pthread_mutex_lock(&update_lock);
sleep(1);
while (update == 1){
pthread_cond_wait(&condition, &update_lock);
}
if (strcmp(ts->command, tb->command) == 0){
matches++;
if (matches >= 3){
break;
}
printf("*** Matched! ***\n");
printf("Matched pair --> (%s, %s)\n", ts->command, tb->command);
ts->valid = 0;
tb->valid = 0;
update = 1;
pthread_cond_broadcast(&condition);
}
ts = ts->next;
pthread_mutex_unlock(&update_lock);
}
tb = tb->next;
}
if (matches >= 3){
break;
}
pthread_mutex_unlock(&reader_lock);
}
return NULL;
}
void *destroy_list(void *args){
pthread_mutex_lock(&update_lock);
info *queues = (info *)args;
destroyList(&(queues->info_buy));
destroyList(&(queues->info_sell));
pthread_mutex_unlock(&update_lock);
return NULL;
}
int main(){
pthread_t workingThreads[5];
pthread_t updateThreads[2];
pthread_t destroy[2];
pthread_cond_init(&condition, NULL);
if (pthread_mutex_init(&reader_lock, NULL) != 0) {
printf("\n mutex init has failed\n");
return 1;
}
if (pthread_mutex_init(&update_lock, NULL) != 0) {
printf("\n mutex init has failed\n");
return 1;
}
node *sell = NULL;
node *buy = NULL;
push(&sell, "Maria");
push(&sell, "Sam");
push(&sell, "Tom");
push(&sell, "Takis");
push(&buy, "Mary");
push(&buy, "Edgar");
push(&buy, "Marx");
push(&buy, "Takis");
//
//
info *ptr = malloc(sizeof(info));
ptr->info_buy = sell;
ptr->info_sell = buy;
for (int i = 0; i < 1; i++){
pthread_create(&(updateThreads[i]), NULL, updateOne, ptr);
}
pthread_create(&(workingThreads[0]), NULL, func, ptr);
pthread_create(&(workingThreads[1]), NULL, func, ptr);
pthread_create(&(workingThreads[2]), NULL, func, ptr);
pthread_create(&(workingThreads[3]), NULL, func, ptr);
pthread_create(&(workingThreads[4]), NULL, func, ptr);
// for (int i = 0; i < 2; i++){
// pthread_create(&(destroy[i]), NULL, destroy_list, ptr);
// }
for (int i = 0; i < 2; i++){
pthread_join(updateThreads[i], NULL);
}
for (int i = 0; i < 5; i++){
pthread_join(workingThreads[i], NULL);
}
pthread_mutex_destroy(&reader_lock);
pthread_mutex_destroy(&update_lock);
pthread_cond_destroy(&condition);
destroyList(&sell);
destroyList(&buy);
return 0;
}
void pop_from_index (node **head, int index){
if ((*head) == NULL){
return;
}
node * temp = (*head);
if (index == 0){
*head = temp->next;
free(temp);
return;
}
for (int i=0; temp!=NULL && i< index - 1; i++){
temp = temp->next;
}
// If position is more than number of nodes
if (temp == NULL || temp->next == NULL)
return;
// Node temp->next is the node to be deleted
// Store pointer to the next of node to be deleted
struct node *next = temp->next->next;
free(temp->next); // Free memory
temp->next = next; // Unlink the deleted node from list
答案 0 :(得分:0)
我认为您正在寻找互斥锁。它非常复杂,但简单地说,它是一种锁定/解锁机制,适用于多个线程尝试访问相同数据的情况,或者换句话说:线程之间的同步。我认为 this article 会让您对这个主题有一个很好的了解。