linux的pthread_mutex_lock只有在第二次尝试时才会生效

问题描述 投票:0回答:1

编辑:我附上一个片段,我已经初始化了attr,所有的调用都很好。

我一直想用PRIO_PROTECT使用mutex,但是第一次调用返回EINVAL,而第二次调用返回0/success.下面是我的做法。

pthread_mutexattr_setprioceiling(&attr, 99);
pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_PROTECT);
pthread_mutex_init(&plock, &attr);
pthread_mutexattr_destroy(&attr);
ret = pthread_mutex_lock(&plock);  //now ret == EINVAL
ret = pthread_mutex_lock(&plock);  // ret == 0

我知道EINVAL意味着调用者的优先级高于上限, 所以我有两个问题:

  1. 为什么第二次就能成功?

  2. 如何将线程的优先级降低到上限? 或者说,将上限设置为线程的优先级?

c linux pthreads posix
1个回答
3
投票

调用 pthread_mutexattr_init 是缺失的。


PTHREAD_PRIO_PROTECT 意味着。

当一个线程拥有一个或多个用PTHREAD_PRIO_PROTECT协议初始化的非生硬的mutexes的时候。应按其优先权或优先权最高限额中的较高者执行。 的所有非生硬的mutexes,并以这个属性初始化,不管其他线程是否在这些非生硬的mutexes上被阻塞。

这意味着 pthread_mutex_lock 将当前线程的优先级设置为 max(current_priority, prioceiling). 您的 prioceiling 是99,这样的优先级需要一个具有实时调度类(FIFO或轮回)的线程。

事实上,任何优先级为 pthread_mutexattr_setprioceiling 需要一个实时调度类。

的值 prioceiling 的最大优先级范围内。SCHED_FIFO.

这是因为你想使用的函数属于 POSIX实时扩展 和默认的 排课 SCHED_OTHER 是为:

这个策略的定义是为了让严格符合要求的应用程序能够以可移植的方式表明它们不再需要实时调度策略。

如果你的应用程序在运行时使用 sudo chrt --fifo 1 <app> 它为你的进程分配了优先级为1的FIFO调度类,这使得它在第一次调用时成功锁定了mutex。


关于为什么第1次调用失败时第2次调用成功,如果我没有弄错的话,这似乎是没有记录的行为,而且是 可能是glibc的一个bug.


0
投票

你是想提升当前执行代码的优先级,还是仅仅想保护一些数据。

如果只是想保护一些数据....

pthread_mutex_t  myMutex = PTHREAD_MUTEX_INITIALIZER;

那么当你想使用mutex时。

pthread_mutex_lock( &myMutex );
... // manipulate the 'critical' data

然后当准备允许另一个线程访问同样的数据时.

... // finished manipulation of the 'critical' data
pthread_mutex_unlock( &myMutex );

注意:初始化还有其他的值,但上面的宏值是最常用的。

© www.soinside.com 2019 - 2024. All rights reserved.