编辑:我正在附加一个片段,我已经初始化了attr,所有调用都很好。
我一直在尝试使用PRIO_PROTECT的互斥体,但第一个调用返回EINVAL,而第二个调用返回零\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意味着呼叫者的优先级高于上限,所以我有两个问题:
为什么它在第二次尝试时有效?
如何将线程的优先级降低到天花板?或者更确切地说,设置线程优先级的上限?
缺少对pthread_mutexattr_init
的调用。
PTHREAD_PRIO_PROTECT
表示:
当线程拥有一个或多个初始化为PTHREAD_PRIO_PROTECT协议,它应在它的优先级或该线程所拥有并用此初始化的所有非健壮互斥的优先级上限中的最高值属性,而不管其他线程是否在任何这些不健壮的互斥。
这意味着pthread_mutex_lock
将当前线程的优先级设置为max(current_priority, prioceiling)
。您的prioceiling
是99,这样的优先级需要一个具有实时调度类(FIFO或循环(的线程。
事实上,pthread_mutexattr_setprioceiling
的任何优先级都需要一个实时调度类:
prioceiling
的值在SCHED_FIFO
定义的最大优先级范围内。
这是因为您想要使用的函数属于POSIX实时扩展,并且默认的调度类SCHED_OTHER
用于:
定义此策略是为了允许严格一致的应用程序能够以可移植的方式指示它们不再需要实时调度策略。
如果您使用sudo chrt --fifo 1 <app>
运行应用程序,它会为您的进程FIFO调度类分配优先级为1的优先级,从而使其在第一次调用时成功锁定互斥对象。
关于为什么第二次调用在第一次调用失败时成功,如果我没有错的话,这似乎是未记录的行为,可能是glibc中的一个错误。
您是想提高当前执行代码的优先级,还是只是保护一些数据。
如果只是试图保护一些数据。。。
pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;
然后当想要使用互斥时:
pthread_mutex_lock( &myMutex );
... // manipulate the 'critical' data
然后,当准备好允许另一个线程访问相同的数据时。
... // finished manipulation of the 'critical' data
pthread_mutex_unlock( &myMutex );
注意:初始化还有其他值,但上面的宏值是最常见的。