linux互斥锁属性

发布于:2025-02-20 ⋅ 阅读:(133) ⋅ 点赞:(0)

PTHREAD_MUTEX_RECURSIVE

PTHREAD_MUTEX_RECURSIVE 是 POSIX 线程(pthread)库中一种特定类型的互斥锁,用于允许同一线程多次获得同一把锁。以下是对 PTHREAD_MUTEX_RECURSIVE 的详细介绍。

递归互斥锁的特点

  1. 允许重复加锁

    • 使用 PTHREAD_MUTEX_RECURSIVE 创建的互斥锁允许同一线程多次锁定。如果一个线程已经持有了这把锁,它可以再次锁定而不会被阻塞。
  2. 锁计数

    • 每次线程成功锁定这把递归互斥锁时,内部计数器会增加。只有在线程调用相应的解锁操作时,计数器才会减少。
    • 当计数器的值回到零时,锁才会被真正释放,允许其他线程获得锁。
  3. 避免死锁

    • 递归锁的设计可以避免由于同一线程重复请求锁而导致的死锁情况。

创建递归互斥锁

要创建一个递归互斥锁,可以使用 pthread_mutexattr_t 结构设置属性。以下是示例代码:

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

int main() {
    pthread_mutex_t mutex;
    pthread_mutexattr_t attr;

    // 初始化互斥锁属性
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);

    // 创建递归互斥锁
    if (pthread_mutex_init(&mutex, &attr) != 0) {
        perror("Mutex init failed");
        return EXIT_FAILURE;
    }

    // 在这里可以使用 mutex...

    // 销毁互斥锁和属性
    pthread_mutex_destroy(&mutex);
    pthread_mutexattr_destroy(&attr);
    
    return EXIT_SUCCESS;
}

使用递归互斥锁

在使用递归互斥锁时,线程可以像下面这样进行加锁和解锁:

void recursive_function(pthread_mutex_t *mutex) {
    pthread_mutex_lock(mutex); // 第一次加锁
    // 这里可以执行某些操作
    pthread_mutex_lock(mutex); // 第二次加锁(允许)
    // 进行更多操作
    pthread_mutex_unlock(mutex); // 第一次解锁
    pthread_mutex_unlock(mutex); // 第二次解锁
}

优缺点

优点
  • 灵活性:允许同一线程在需要的情况下多次获取锁,适用于需要递归调用的场景。
  • 避免死锁:有效防止同一线程因重复加锁而导致的死锁。
缺点
  • 性能开销:递归锁的实现通常比普通互斥锁有更高的性能开销,因为需要维护锁的计数器。
  • 复杂性:使用递归锁可能会导致代码复杂性增加,开发者需要小心管理锁的获取和释放。

PTHREAD_PRIO_INHERIT

PTHREAD_PRIO_INHERIT 是 POSIX 线程(pthread)库中的一个互斥锁属性,用于实现优先级继承机制。这种机制的目的是解决优先级反转问题,确保高优先级线程能够及时执行。以下是有关 PTHREAD_PRIO_INHERIT 的详细说明:

优先级反转问题

在多线程环境中,优先级反转问题会发生在以下情况下:

  1. 低优先级线程持有一个锁。
  2. 高优先级线程请求该锁并被阻塞。
  3. 中优先级线程获得 CPU 资源并执行,导致高优先级线程的执行被延迟。

这种情况可能导致高优先级任务的响应时间不符合实时要求。

优先级继承机制

使用 PTHREAD_PRIO_INHERIT 属性时,当高优先级线程请求锁而低优先级线程持有该锁时,为了避免高优先级线程被阻塞,低优先级线程的优先级会被临时提升到高优先级线程的优先级,低优先级线程在完成其任务后释放锁,优先级恢复到原来的值,此时高优先级线程可以获得锁并继续执行。这样可以:

  • 减少高优先级线程的等待时间:通过提升持锁线程的优先级,可以快速释放锁。
  • 提高系统的实时性和可预测性

使用方法

要使用 PTHREAD_PRIO_INHERIT,需要创建互斥锁时设置相应的属性。以下是示例代码:

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

int main() {
    pthread_mutex_t mutex;
    pthread_mutexattr_t attr;

    // 初始化互斥锁属性
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); // 设置优先级继承

    pthread_mutex_init(&mutex, &attr);

    // 使用 mutex...

    // 销毁互斥锁和属性
    pthread_mutex_destroy(&mutex);
    pthread_mutexattr_destroy(&attr);

    return 0;
}

优缺点

优点
  1. 避免优先级反转

    • 通过临时提升低优先级线程的优先级,确保高优先级线程能够及时执行。
  2. 提高系统可预测性

    • 在实时系统中,确保重要任务能够按时完成。
  3. 适用于复杂场景

    • 在多线程和多优先级的环境中,能够有效管理线程执行顺序。
缺点
  1. 复杂性

    • 优先级继承机制的实现可能会增加系统设计的复杂性,特别是在涉及多个锁和线程时。
  2. 饥饿问题

    • 低优先级线程可能会因为不断被提升优先级而无法获得执行机会,导致饥饿现象。
  3. 性能开销

    • 临时提升优先级的机制可能会引入额外的性能开销,尤其是在高频率的加锁和解锁操作中。

实际应用场景

  • 实时系统

    • 在实时操作系统中,使用 PTHREAD_PRIO_INHERIT 可以确保关键任务的及时响应。
  • 嵌入式系统

    • 在嵌入式应用中,实时性要求高,优先级继承可以帮助简化线程调度。
  • 复杂多线程应用

    • 在需要处理多个线程和锁的复杂应用程序中,使用优先级继承可以提高系统的可预测性和稳定性。