pthread_rBlock的优先级?
考虑此示例代码:pthread_rBlock的优先级?,c,multithreading,pthreads,read-write,C,Multithreading,Pthreads,Read Write,考虑此示例代码: #include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <unistd.h> void *func1(void *); void *func2(void *); static pthread_rwlock_t rwLock = PTHREAD_RWLOCK_INITIALIZER; int main() { pthread_t thr
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
void *func1(void *);
void *func2(void *);
static pthread_rwlock_t rwLock = PTHREAD_RWLOCK_INITIALIZER;
int main() {
pthread_t thread1;
pthread_t thread2;
pthread_create(&thread1, NULL, func1, NULL);
sleep(1);
int i;
for (i = 0; i < 3; i++) {
pthread_create(&thread2, NULL, func2, (void *)(i + 1));
}
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
void *func1(void *arg) {
int j;
for(j = 0; j < 10; j++) {
printf("func 1: trying lock\n");
pthread_rwlock_wrlock(&rwLock);
printf("func 1: lock aquired, sleep 1 sec...\n");
sleep(1);
pthread_rwlock_unlock(&rwLock);
}
}
void *func2(void *arg) {
int true = 1;
while(true) {
pthread_rwlock_rdlock(&rwLock);
printf("func 2: thread %i: lock aquired, sleep 1 sec... \n", (int)arg);
sleep(1);
pthread_rwlock_unlock(&rwLock);
}
}
添加了另一个示例
#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#define SIZE 10000
void *writerFunc(void *);
void *readerFunc1(void *);
void *readerFunc2(void *);
int setSchedulePolicyTo2(void);
static pthread_rwlock_t rwLock = PTHREAD_RWLOCK_INITIALIZER;
int main() {
pthread_t readerThread1;
pthread_t readerThread2;
pthread_t writerThread;
pthread_create(&readerThread1, NULL, readerFunc1, NULL);
sleep(1);
pthread_create(&readerThread1, NULL, writerFunc, NULL);
sleep(1);
pthread_create(&readerThread2, NULL, readerFunc2, NULL);
pthread_join(readerThread1, NULL);
pthread_join(readerThread2, NULL);
pthread_join(writerThread, NULL);
return 0;
}
void *writerFunc(void *arg) {
printf(" writer's scheduling policy: %d\n", setSchedulePolicyTo2());
printf("writer 1: trying to acquire rw lock...(on hold)\n");
pthread_rwlock_wrlock(&rwLock); // Note ..._wrlock
printf("writer 1: rw lock acquired \n");
pthread_rwlock_unlock(&rwLock);
}
void *readerFunc1(void *arg) {
printf(" reader1's scheduling policy: %d\n", setSchedulePolicyTo2());
printf("reader 1: trying to acquire rw lock...(on hold)\n");
pthread_rwlock_rdlock(&rwLock);
printf("reader 1: rw lock acquired \n");
sleep(3); // enough time to let reader 2 to acquire rw lock before this reader releases it.
pthread_rwlock_unlock(&rwLock);
printf("reader 1: rw lock released \n");
}
void *readerFunc2(void *arg) {
printf(" reader2's scheduling policy: %d\n", setSchedulePolicyTo2());
printf("reader 2: trying to acquire rw lock...(on hold)\n");
pthread_rwlock_rdlock(&rwLock);
printf("reader 2: rw lock acquired \n");
sleep(2);
pthread_rwlock_unlock(&rwLock);
printf("reader 2: rw lock released \n");
}
int setSchedulePolicyTo2() {
struct sched_param sp;
sp.sched_priority = 10;
int policy;
int j;
if((j = pthread_setschedparam(pthread_self(), SCHED_RR, &sp)) != 0) {
printf("error: %s \n", strerror(errno));
}
if((j = pthread_getschedparam(pthread_self(), &policy, &sp)) != 0) {
printf("error: %s \n", strerror(errno));
}
return policy;
}
根据pthread_rwlockrdlock的manpage,读卡器2不应该获取锁,因为有具有相同优先级的writer处于保留状态,并且所有线程的调度策略都设置为SCHED_RR(2)
如果支持线程执行调度选项,则
锁中涉及的线程正在执行调度
策略SCHED_FIFO或SCHED_RR,调用线程不应获取
如果写入程序持有锁,或者如果写入程序的级别更高或相等,则为锁
锁上的优先级被阻塞;否则,调用线程将
拿到锁
func 1: trying lock
func 1: lock aquired, sleep 1 sec...
func 1: trying lock
func 1: lock aquired, sleep 1 sec...
func 1: trying lock
func 2: thread 1: lock aquired, sleep 1 sec...
func 2: thread 3: lock aquired, sleep 1 sec...
func 2: thread 2: lock aquired, sleep 1 sec...
func 2: thread 2: lock aquired, sleep 1 sec...
func 2: thread 3: lock aquired, sleep 1 sec...
func 2: thread 1: lock aquired, sleep 1 sec...
func 2: thread 2: lock aquired, sleep 1 sec...
func 2: thread 3: lock aquired, sleep 1 sec...
func 2: thread 1: lock aquired, sleep 1 sec...
func 2: thread 3: lock aquired, sleep 1 sec...
func 2: thread 1: lock aquired, sleep 1 sec...
func 2: thread 2: lock aquired, sleep 1 sec...
func 2: thread 3: lock aquired, sleep 1 sec...
func 2: thread 2: lock aquired, sleep 1 sec...
func 2: thread 1: lock aquired, sleep 1 sec...
func 2: thread 3: lock aquired, sleep 1 sec...
func 2: thread 1: lock aquired, sleep 1 sec...
func 2: thread 2: lock aquired, sleep 1 sec...
...
只有当两个读卡器都释放了rw锁时,编写器才能获得锁。仔细阅读手册页
注意你引用的句子
如果写入程序没有持有锁,并且锁上没有被阻止的写入程序,则调用线程将获取读锁
not是否表示如果有写入程序被阻止,读卡器将不会获得锁(if
而不是if且仅当
)
以下内容将使用文档。
引用的句子后面的段落指定了pthread\u rwlock\u rdlock()
在锁上有被阻止的写入程序时如何操作:
[TPS][Option Start]如果支持线程执行调度选项,并且
锁中涉及的线程正在执行调度
策略SCHED_FIFO或SCHED_RR,调用线程不应获取
如果写入程序持有锁,或者如果写入程序的级别更高或相等,则为锁
优先级在锁上被阻塞;否则,调用线程将
获取锁。[选项结束]
[TPS TSP][Option Start]如果线程执行调度选项为
支持,并且锁中涉及的线程正在使用
SCHED_零星调度策略,调用线程不应获取
如果写入程序持有锁,或者如果写入程序的级别更高或相等,则为锁
优先级在锁上被阻塞;否则,调用线程将
获取锁。[选项结束]
如果不支持线程执行调度选项,则为
实现定义了调用线程是否获取锁
当写入程序未持有锁且有写入程序被阻止时
锁。如果写入程序持有锁,则调用线程不应
获取读锁。如果未获取读锁,则调用
线程将阻塞,直到它能够获得锁。调用线程
如果在调用时持有写锁,则可能会死锁
因此,要提供完整的答案,您需要说明您的实现是否提供了线程执行调度选项,如果提供了,则说明选择了哪个调度策略
要查看当前调度策略是什么(如果您在Linux上),请运行以下程序:
#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
int main(void)
{
printf("round-robin scheduling policy: %d\n", SCHED_RR);
printf("fifo scheduling policy: %d\n", SCHED_FIFO);
printf("other scheduling policy: %d\n", SCHED_OTHER);
pthread_attr_t ta;
pthread_getattr_np(pthread_self(), &ta);
int ts;
pthread_attr_getschedpolicy(&ta, &ts);
printf("current scheduling policy: %d\n", ts);
}
定义GNU源
#包括
#包括
内部主(空)
{
printf(“循环调度策略:%d\n”,SCHED\u RR);
printf(“fifo调度策略:%d\n”,调度fifo);
printf(“其他调度策略:%d\n”,SCHED_other);
pthread_attr_ta;
pthread_getattr_np(pthread_self(),&ta);
int ts;
pthread_attr_getschedpolicy(&ta,&ts);
printf(“当前计划策略:%d\n”,ts);
}
除非当前的调度策略是循环调度或Fifo,否则引用文档的前两段不适用。在这种情况下,调度行为是由实现定义的。特别是,读写器锁很容易偏好读写器,在这种情况下,编写器几乎肯定永远无法运行我们的程序,因为读卡器正在锁保护上序列化stdout
(通过printf()
),根据C11标准草案n1570:
7.21输入/输出
7.21.2溪流
7每个流都有一个关联的锁,用于防止多个执行线程访问流时发生数据争用,并限制多个线程执行的流操作的交错。一次只能有一个线程持有该锁。该锁是可重入的:单个线程在给定时间可以多次持有该锁。
因为这个锁在保持readlock的同时也保持着,而
sleep()
也会在持有读锁时执行,读卡器在释放读锁和再次获取读锁之间不会做任何事情,任何时候都没有读卡器持有读锁的可能性非常小。因此,编写器从来没有机会。功能1打印的顺序不是很有趣吗?@user58697我一定错过了复制1我们再次运行程序检查输出,并在我的操作中更新了一个。我试图进一步阅读手册。您引用的3段都说明,在我的情况下,读者不应获取锁,因为我在块上有一个writer,但实现定义的部分除外,这是唯一一个读卡器可能获得锁的情况。我不确定这里定义的实现是什么意思?我的整个程序都在op中,我使用“gcc main.c-lpthread”构建和运行。/a.out在linux平台上。我已将#include更新到我的op中以完成我的程序。#include
s很好,但它们没有说明任何关于调度策略的内容。我已更新了答案,以显示如何在linux上找到当前的调度策略。好的,我已经阅读了更多关于调度的内容,并开始接受没有简单的方法可以知道g实现定义的行为(运行您的程序给了我0:其他调度策略).所以我试着做了更简单的例子,我在我的作品中更新了。我不希望你在我这个看似无用的问题上浪费更多的时间,但为了学习,我试图理解为什么手册页与我的程序相矛盾,这意味着要么我疯了,要么我在读手册页
#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
int main(void)
{
printf("round-robin scheduling policy: %d\n", SCHED_RR);
printf("fifo scheduling policy: %d\n", SCHED_FIFO);
printf("other scheduling policy: %d\n", SCHED_OTHER);
pthread_attr_t ta;
pthread_getattr_np(pthread_self(), &ta);
int ts;
pthread_attr_getschedpolicy(&ta, &ts);
printf("current scheduling policy: %d\n", ts);
}