线程退出但仍保持互斥

thread exit but still hold mutex

持有互斥量的线程已终止。另一个线程在调用 "pthread_mutex_lock" 时会死锁,尽管我使用 "PTHREAD_MUTEX_ERRORCHECK" 属性。

#include <pthread.h>
#include <iostream>
#include <unistd.h>

using namespace std;

pthread_mutex_t mutex;

void *handler(void *)
{
    cout << "child thread" << endl;
    int ret = pthread_mutex_lock(&mutex);
    cout << "child ret: " << ret << endl;
    pthread_exit(NULL);
}

int main()
{
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);

    pthread_mutex_init(&mutex, &attr);
    pthread_mutexattr_destroy(&attr);

    pthread_t tid;
    pthread_create(&tid, NULL, handler, NULL);

    sleep(2);
    cout << "father awake" << endl;

    int ret = pthread_mutex_lock(&mutex);
    cout << "father ret: " << ret << endl;
    return 0;
}

输出:

[LINUX 环境]: Linux ubuntu 3.19.0-25-generic #26~14.04.1-Ubuntu SMP

您可能正在考虑互斥体 (pthread_mutexattr_setrobust()) 的 robust 属性,而不是 errorcheck 类型互斥体。一个健壮的互斥量会通知您的主线程互斥量锁的持有者已终止并带有 EOWNERDEAD。

PTHREAD_MUTEX_ERRORCHECK 类型,另一方面,只是 guards against three kinds of errors:

  1. 试图递归锁定自己锁定的互斥量(此处不适用)
  2. 试图解锁被另一个线程锁定的互斥量(此处不适用)
  3. 正在尝试解锁已解锁的互斥量(此处不适用)

这是一个使用 pthread_mutexattr_setrobust 调用允许将从未解锁的 mutex 设置回一致状态的小示例:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

pthread_mutex_t lock;

void dropped_thread(void)
{
    printf("Setting lock...\n");
    pthread_mutex_lock(&lock);
    printf("Lock set, now exiting without unlocking...\n");
    pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
    pthread_t lock_getter;
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST); 
    pthread_mutex_init(&lock, &attr);
    pthread_mutexattr_destroy(&attr);
    pthread_create(&lock_getter, NULL, (void *) dropped_thread, NULL);
    sleep(2);

    printf("Inside main\n");
    printf("Attempting to acquire unlocked mutex?\n");

    pthread_mutex_consistent(&lock);
    pthread_mutex_unlock(&lock);
    pthread_mutex_lock(&lock);

    printf("Successfully acquired lock!\n");
    pthread_mutex_destroy(&lock);
    return 0;
}

正如您在设置 mutex 稳健性后调用 pthread_mutex_consistent 所见,其状态再次标记为一致。