pthread 执行陷入死循环
pthread execution fall in infinite loop
我正在尝试的是:
- 创建了四个线程(主线程创建了 3 个线程,线程 3 创建了线程 4)
- 所有线程共享一个共享内存对象。
- 另一个共享内存对象在线程二和线程四之间共享。
- 线程 4 等待来自线程 2 的信号,直到创建共享内存对象。
- 都是互斥的。
但是我的程序陷入了死循环。需要解决方案的帮助。
下面是我的源代码:
#include <assert.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h> /* for ftruncate */
#include <sys/mman.h> /* for shm_ and mmap */
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
pthread_t T1, T2, T3, T4;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex3 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_one;
int fd;
int *shared_heap;
int *shared_heap2;
int *shared_heap3;
int counter = 0;
//thread one creator func
// *argv is the shared mem obj which is passed while thread is created
void* task1(void *argv) {
int *var = (int*) argv;
pthread_mutex_lock(&mutex);
*var += 1;
pthread_mutex_unlock(&mutex);
return NULL;
}
//thread two creator func
// *argv is the shared mem obj which is passed while thread is created
void* task2(void *argv) {
int *var = (int*) argv;
pthread_mutex_lock(&mutex);
*var += 1;
pthread_mutex_unlock(&mutex);
//another mutex to create another shared mem obj
pthread_mutex_lock(&mutex2);
shared_heap2 = (int *) mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,MAP_SHARED, fd, 0);
assert(shared_heap2);
counter++;
//signal
if (counter > 0) {
pthread_cond_signal(&cond_one);
printf("signal is sent \n");
}
pthread_mutex_unlock(&mutex2);
return NULL;
}
//thread four creator func
//created from thread three
// *argv is the shared mem obj which is passed while thread is created
void* task4(void *argv) {
int *var = (int*) argv;
pthread_mutex_lock(&mutex);
*var += 1;
pthread_mutex_unlock(&mutex);
pthread_mutex_lock(&mutex2);
//waiting for signal from thread two
while (counter > 0) {
pthread_cond_wait(&cond_one, &mutex2);
printf("waiting for signal. \n");
}
*shared_heap2 = 9;
pthread_mutex_unlock(&mutex2);
return NULL;
}
////thread three creator func
void* task3(void *argv) {
int *var = (int*) argv;
pthread_mutex_lock(&mutex);
*var += 1;
pthread_mutex_unlock(&mutex);
//thread four is create from here
assert(pthread_create(&T4, NULL, &task4, var) == 0);
assert(pthread_join(T4, NULL) == 0);
return NULL;
}
int main(void) {
pthread_cond_init(&cond_one, NULL);
fd = shm_open("test_shared_var_heap_local", O_CREAT | O_RDWR,S_IRUSR | S_IWUSR);
assert(fd != -1);
assert(ftruncate(fd, sizeof(int)) == 0);
shared_heap = (int *) mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,MAP_SHARED, fd, 0);
assert(shared_heap);
printf("main \n");
//assert(shared_heap);
assert(pthread_create(&T1, NULL, &task1, shared_heap) == 0);
assert(pthread_create(&T2, NULL, &task2, shared_heap) == 0);
assert(pthread_create(&T3, NULL, &task3, shared_heap) == 0);
printf("three \n");
assert(pthread_join(T1, NULL) == 0);
assert(pthread_join(T3, NULL) == 0);
assert(pthread_join(T2, NULL) == 0);
return 0;
}
But my program falls in infinite loop.
你会
while (counter > 0) {
pthread_cond_wait(&cond_one, &mutex2);
printf("waiting for signal. \n");
}
但是 counter 只是在 task2 中设置为 1 一次,没有理由退出 while
反正这不是一个人的问题,在task2下mutext2设置了counter到 1 并发送信号,所以
第一种可能task4在设置为1之前已经完成,信号没用
else task2 比 运行 更快并在 task4 之前获得 mutex2 ,所以当 task4 会得到 mutex2 信号已经发送,但是信号没有被缓冲所以永远不会被接收通过 task4
如果你想确保task2中受mutex2保护的代码在task4[=84之前执行=] 完成受 mutex2 保护的代码:
- counter 仍初始化为 0 :
int counter = 0;
- in task4 when mutex2 is get just set counter to 1 and remove the useless在解锁 mutext2
之前测试 if (counter > 0)
在所有情况下发送信号
- in task2 when mutext2 is get replace the
while (counter > 0) {
by if (counter == 0) {
这样 :
- if task4 在 task2 之前得到 mutex2 因为 counter仍然是0task4等待信号(即解锁mutext2),task2可以得到mutext2 并发送信号并解锁 mutext2 并完成,task4 收到信号(锁定 mutext2) 然后解锁 mutext2 并完成
- if task2 在 task4 之前获取 mutext2 它设置 counter to 1 and unlock mutext2 and finished, task4 can get mutext2 and does not wait对于信号因为 counter 是 1 所以解锁 mutext2 并完成
我正在尝试的是:
- 创建了四个线程(主线程创建了 3 个线程,线程 3 创建了线程 4)
- 所有线程共享一个共享内存对象。
- 另一个共享内存对象在线程二和线程四之间共享。
- 线程 4 等待来自线程 2 的信号,直到创建共享内存对象。
- 都是互斥的。
但是我的程序陷入了死循环。需要解决方案的帮助。
下面是我的源代码:
#include <assert.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h> /* for ftruncate */
#include <sys/mman.h> /* for shm_ and mmap */
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
pthread_t T1, T2, T3, T4;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex3 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_one;
int fd;
int *shared_heap;
int *shared_heap2;
int *shared_heap3;
int counter = 0;
//thread one creator func
// *argv is the shared mem obj which is passed while thread is created
void* task1(void *argv) {
int *var = (int*) argv;
pthread_mutex_lock(&mutex);
*var += 1;
pthread_mutex_unlock(&mutex);
return NULL;
}
//thread two creator func
// *argv is the shared mem obj which is passed while thread is created
void* task2(void *argv) {
int *var = (int*) argv;
pthread_mutex_lock(&mutex);
*var += 1;
pthread_mutex_unlock(&mutex);
//another mutex to create another shared mem obj
pthread_mutex_lock(&mutex2);
shared_heap2 = (int *) mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,MAP_SHARED, fd, 0);
assert(shared_heap2);
counter++;
//signal
if (counter > 0) {
pthread_cond_signal(&cond_one);
printf("signal is sent \n");
}
pthread_mutex_unlock(&mutex2);
return NULL;
}
//thread four creator func
//created from thread three
// *argv is the shared mem obj which is passed while thread is created
void* task4(void *argv) {
int *var = (int*) argv;
pthread_mutex_lock(&mutex);
*var += 1;
pthread_mutex_unlock(&mutex);
pthread_mutex_lock(&mutex2);
//waiting for signal from thread two
while (counter > 0) {
pthread_cond_wait(&cond_one, &mutex2);
printf("waiting for signal. \n");
}
*shared_heap2 = 9;
pthread_mutex_unlock(&mutex2);
return NULL;
}
////thread three creator func
void* task3(void *argv) {
int *var = (int*) argv;
pthread_mutex_lock(&mutex);
*var += 1;
pthread_mutex_unlock(&mutex);
//thread four is create from here
assert(pthread_create(&T4, NULL, &task4, var) == 0);
assert(pthread_join(T4, NULL) == 0);
return NULL;
}
int main(void) {
pthread_cond_init(&cond_one, NULL);
fd = shm_open("test_shared_var_heap_local", O_CREAT | O_RDWR,S_IRUSR | S_IWUSR);
assert(fd != -1);
assert(ftruncate(fd, sizeof(int)) == 0);
shared_heap = (int *) mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,MAP_SHARED, fd, 0);
assert(shared_heap);
printf("main \n");
//assert(shared_heap);
assert(pthread_create(&T1, NULL, &task1, shared_heap) == 0);
assert(pthread_create(&T2, NULL, &task2, shared_heap) == 0);
assert(pthread_create(&T3, NULL, &task3, shared_heap) == 0);
printf("three \n");
assert(pthread_join(T1, NULL) == 0);
assert(pthread_join(T3, NULL) == 0);
assert(pthread_join(T2, NULL) == 0);
return 0;
}
But my program falls in infinite loop.
你会
while (counter > 0) {
pthread_cond_wait(&cond_one, &mutex2);
printf("waiting for signal. \n");
}
但是 counter 只是在 task2 中设置为 1 一次,没有理由退出 while
反正这不是一个人的问题,在task2下mutext2设置了counter到 1 并发送信号,所以
第一种可能task4在设置为1之前已经完成,信号没用
else task2 比 运行 更快并在 task4 之前获得 mutex2 ,所以当 task4 会得到 mutex2 信号已经发送,但是信号没有被缓冲所以永远不会被接收通过 task4
如果你想确保task2中受mutex2保护的代码在task4[=84之前执行=] 完成受 mutex2 保护的代码:
- counter 仍初始化为 0 :
int counter = 0;
- in task4 when mutex2 is get just set counter to 1 and remove the useless在解锁 mutext2 之前测试
- in task2 when mutext2 is get replace the
while (counter > 0) {
byif (counter == 0) {
if (counter > 0)
在所有情况下发送信号
这样 :
- if task4 在 task2 之前得到 mutex2 因为 counter仍然是0task4等待信号(即解锁mutext2),task2可以得到mutext2 并发送信号并解锁 mutext2 并完成,task4 收到信号(锁定 mutext2) 然后解锁 mutext2 并完成
- if task2 在 task4 之前获取 mutext2 它设置 counter to 1 and unlock mutext2 and finished, task4 can get mutext2 and does not wait对于信号因为 counter 是 1 所以解锁 mutext2 并完成