В моей тестовой программе я запускаю два потока, каждый из которых выполняет следующую логику:
1) pthread_mutex_lock()
2) sleep(1)
3) pthread_mutex_unlock()
Однако я обнаружил, что через некоторое время один из двух потоков навсегда заблокирует pthread_mutex_lock (), тогда как другой поток будет работать нормально. Это очень странное поведение, и я думаю, что это может быть серьезной проблемой. Руководством по Linux, sleep () не запрещается, когда получен pthread_mutex_t. Итак, мой вопрос: это реальная проблема или есть какая-то ошибка в моем коде?
Ниже приводится тестовая программа. В коде выходные данные 1-го потока направляются в stdout, а выходные данные второго потока - в stderr. Таким образом, мы можем проверить эти два разных вывода, чтобы увидеть, заблокирован ли поток.
Я проверил его на ядре Linux (2.6.31) и (2.6.9). Оба результата одинаковы.
//======================= Test Program ===========================
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#define THREAD_NUM 2
static int data[THREAD_NUM];
static int sleepFlag = 1;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static void * threadFunc(void *arg)
{
int* idx = (int*) arg;
FILE* fd = NULL;
if (*idx == 0)
fd = stdout;
else
fd = stderr;
while(1) {
fprintf(fd, "\n[%d]Before pthread_mutex_lock is called\n", *idx);
if (pthread_mutex_lock(&mutex) != 0) {
exit(1);
}
fprintf(fd, "[%d]pthread_mutex_lock is finisheded. Sleep some time\n", *idx);
if (sleepFlag == 1)
sleep(1);
fprintf(fd, "[%d]sleep done\n\n", *idx);
fprintf(fd, "[%d]Before pthread_mutex_unlock is called\n", *idx);
if (pthread_mutex_unlock(&mutex) != 0) {
exit(1);
}
fprintf(fd, "[%d]pthread_mutex_unlock is finisheded.\n", *idx);
}
}
// 1. compile
// gcc -o pthread pthread.c -lpthread
// 2. run
// 1) ./pthread sleep 2> /tmp/error.log # Each thread will sleep 1 second after it acquires pthread_mutex_lock
// ==> We can find that /tmp/error.log will not increase.
// or
// 2) ./pthread nosleep 2> /tmp/error.log # No sleep is done when each thread acquires pthread_mutex_lock
// ==> We can find that both stdout and /tmp/error.log increase.
int main(int argc, char *argv[]) {
if ((argc == 2) && (strcmp(argv[1], "nosleep") == 0))
{
sleepFlag = 0;
}
pthread_t t[THREAD_NUM];
int i;
for (i = 0; i < THREAD_NUM; i++) {
data[i] = i;
int ret = pthread_create(&t[i], NULL, threadFunc, &data[i]);
if (ret != 0) {
perror("pthread_create error\n");
exit(-1);
}
}
for (i = 0; i < THREAD_NUM; i++) {
int ret = pthread_join(t[i], (void*)0);
if (ret != 0) {
perror("pthread_join error\n");
exit(-1);
}
}
exit(0);
}
Это вывод:
На терминале, где запущена программа:
root@skyscribe:~# ./pthread sleep 2> /tmp/error.log
[0]Before pthread_mutex_lock is called
[0]pthread_mutex_lock is finisheded. Sleep some time
[0]sleep done
[0]Before pthread_mutex_unlock is called
[0]pthread_mutex_unlock is finisheded.
...
На другом терминале посмотреть файл /tmp/error.log
root@skyscribe:~# tail -f /tmp/error.log
[1]Before pthread_mutex_lock is called
И никакие новые строки не выводятся из /tmp/error.log