几天来,我一直在处理线程池中的一个问题。我尝试了所有类型的不同的东西,但我似乎无法解决这个问题。我制作了一个简单的版本来重现该问题。
代码:
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
struct bsem_t bsem;
pthread_t threads[2];
/* Binary semaphore */
typedef struct bsem_t {
pthread_mutex_t mutex;
pthread_cond_t cond;
int v;
} bsem_t;
void bsem_post(bsem_t *bsem) {
pthread_mutex_lock(&bsem->mutex);
bsem->v = 1;
pthread_cond_broadcast(&bsem->cond);
pthread_mutex_unlock(&bsem->mutex);
}
void bsem_wait(bsem_t *bsem) {
pthread_mutex_lock(&bsem->mutex);
while (bsem->v != 1) {
pthread_cond_wait(&bsem->cond, &bsem->mutex);
}
bsem->v = 0;
pthread_mutex_unlock(&bsem->mutex);
}
/* Being called by each thread on SIGUSR1 */
void thread_exit(){
printf("%u: pthread_exit()\n", (int)pthread_self());
pthread_exit(NULL);
}
/* Startpoint for each thread */
void thread_do(){
struct sigaction act;
act.sa_handler = thread_exit;
sigaction(SIGUSR1, &act, NULL);
while(1){
bsem_wait(&bsem); // Each thread is blocked here
puts("Passed semaphore");
}
}
/* Main */
int main(){
bsem.v = 0;
pthread_create(&threads[0], NULL, (void *)thread_do, NULL);
pthread_create(&threads[1], NULL, (void *)thread_do, NULL);
pthread_detach(threads[0]);
pthread_detach(threads[1]);
puts("Created threads");
sleep(2);
pthread_kill(threads[0], SIGUSR1);
pthread_kill(threads[1], SIGUSR1);
puts("Killed threads");
sleep(10);
return 0;
}
代码的作用是创建两个线程。两个线程都在一个二进制信号量(bsem_wait)上等待。然后在他们等待时,我向SIGUSR1
两者发送信号,导致pthread_exit()
在每个线程上执行。在我的终端上,它显示一切都按计划进行。
输出:
Created threads
Killed threads
2695145216: pthread_exit()
2686752512: pthread_exit()
问题
尽管输出看起来是正确的,但 usingpstree
表明只有两个线程中的一个死掉了。另一个线程保持活动状态,直到整个程序退出。为什么是这样?
更新
用普通信号量替换我的自定义二进制信号量似乎没有明显的原因解决了这个问题。
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <semaphore.h>
sem_t sem;
pthread_t threads[2];
/* Caller thread will exit */
void thread_exit(){
printf("%u: pthread_exit()\n", (int)pthread_self());
pthread_exit(NULL);
}
/* Startpoint for each thread */
void* thread_do(){
struct sigaction act;
act.sa_handler = thread_exit;
sigaction(SIGUSR1, &act, NULL);
while(1){
sem_wait(&sem); // Each thread is blocked here
puts("Passed semaphore");
}
}
/* Main */
int main(){
sem_init(&sem, 0, 0); // Normal semaphore
pthread_create(&threads[0], NULL, thread_do, NULL);
pthread_create(&threads[1], NULL, thread_do, NULL);
pthread_detach(threads[0]);
pthread_detach(threads[1]);
puts("Created threads in pool");
sleep(2);
//PROBLEM
pthread_kill(threads[0], SIGUSR1);
pthread_kill(threads[1], SIGUSR1);
puts("Destroyed pool");
sleep(10);
return 0;
}