我正在做一项作业,要求我 1. 打开一个文件并在一个线程中读取该文件,2. 当每个值被逐个读取时,将每个值保存到全局变量,然后启动一个互斥体,因此 3第二个线程可以使用该全局变量,然后在线程 1 读取下一个值并重复该过程之前将其写入文件。我在对互斥体进行计时时遇到问题,以便一旦读取某个值,第二个线程就可以写入该值。目前,线程 2 仅打印出 0 并且没有进行迭代。我不确定我做错了什么。我的想法是,当我锁定线程时,它会在转到线程 2 之前快速迭代。这是我的源代码:
#include <stdio.h>
#include <stdio.h>
#include <pthread.h>
int value;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *inputThread(void * args) {
FILE *input = fopen("hw4.in", "r");
while(!feof(input)) {
//printf("Thread locked.\n");
fscanf(input, "%d\n", &value);
pthread_mutex_lock(&mutex);
printf("value: %d\n", value);
//printf("Thread unlocked.\n");
pthread_mutex_unlock(&mutex);
}
fclose(input);
pthread_exit(NULL);
}
void *counting(void *args) {
printf("Value: %d\n", value);
pthread_exit(NULL);
}
int main() {
//Creating thread1
pthread_t pt1;
pthread_create(&pt1, NULL, inputThread, NULL);
//Creating thread2
pthread_t pt2;
pthread_create(&pt2, NULL, counting, NULL);
//Joining thread1
pthread_join(pt1, NULL);
pthread_join(pt2, NULL);
}
编辑:执行此操作的正确方法是让 thread2 也调用 inputThread 并在 while 循环中锁定互斥体,并在 while 循环之后编写另一个语句来写入文件并在此之后关闭互斥体?就像我必须在同一个函数中执行这两项操作?
最佳答案
互斥体在一组线程之间提供MUT双向排除。一般的想法是,每个线程在执行操作之前锁定(相同的)互斥锁,在此期间必须排除所有其他线程运行,然后在完成后解锁它。一次只有一个线程可以锁定互斥锁,因此会出现排除。
此外,互斥体还提供内存屏障语义,以便任何线程在释放互斥体之前执行的内存写入操作都保证在锁定互斥体后可以被其他线程看到。如果不使用互斥体或其他某种同步对象,则不能保证情况会如此。
您需要这两个属性。您需要写入器查看读取器读取的值,并且需要它等待读取器读取每个值,然后再尝试写入它。您还需要读取器在每次读取后等待,直到写入器写入读取的值,以免在写入器有机会写入之前用新值替换它。因此,每个线程必须仅在锁定互斥锁的情况下访问变量 value
,而且还必须在每次访问后解锁互斥锁,以允许其他线程继续进行。
不幸的是,仅互斥锁不足以解决您的问题。它们可以阻止您的线程同时运行,但它们本身不能使您的线程交替运行,这就是你需要。互斥体通常与另一种同步对象(“条件变量”)结合使用,以规定每个线程在且仅在其应该执行的时间运行。 CV,正确使用,通常是那里的头条新闻,但它需要与互斥体一起使用。
您可以在这里找到许多答案以及许多有关如何使用互斥体和 CV 使线程正确轮流的网络教程。您可以尝试在谷歌上搜索“生产者消费者”,因为这是您要解决的问题类别的通用名称。将“互斥体”和“条件变量”放入搜索词中,您应该会在前几个匹配项中找到黄金。
关于c - 使用互斥锁同步 pthread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52489108/