gpt4 book ai didi

c - pthread_rwlock的优先级?

转载 作者:行者123 更新时间:2023-11-30 19:02:25 40 4
gpt4 key购买 nike

考虑这个示例代码:

#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);
}
}

我有一个线程在 func1 中循环,其中请求写入锁定 1 秒,另外 3 个线程在 func 2 中循环,其中请求读取锁定 1 秒。

关于pthread_rwlock_rdlock手册页上写着“如果写入者没有持有锁并且没有写入者被锁定,则调用线程将获取读锁。”。从我在第 5 行的输出粘贴中,您可以看到“func 1:尝试锁定”上的写入者显然处于阻塞状态,那么为什么我的读者无论如何都会获得锁定呢?第 5 行之后,每秒打印 3 行。减少读取器线程会增加写入器获得锁的机会。

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...
...

添加了另一个示例

#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;
}

输出:

$ gcc main.c -pthread
$ sudo ./a.out
reader1's scheduling policy: 2
reader 1: trying to acquire rw lock...(on hold)
reader 1: rw lock acquired
writer's scheduling policy: 2
writer 1: trying to acquire rw lock...(on hold)
reader2's scheduling policy: 2
reader 2: trying to acquire rw lock...(on hold)
reader 2: rw lock acquired
reader 1: rw lock released
reader 2: rw lock released
writer 1: rw lock acquired
Segmentation fault (end of program)

根据 pthread_rwlock_rdlock 的手册页,读取器 2 不应该获取锁,因为有具有相同优先级的写入器处于搁置状态,并且所有线程的调度策略都设置为 SCHED_RR (2)。

If the Thread Execution Scheduling option is supported, and the threads involved in the lock are executing with the scheduling policies SCHED_FIFO or SCHED_RR, the calling thread shall not acquire the lock if a writer holds the lock or if writers of higher or equal priority are blocked on the lock; otherwise, the calling thread shall acquire the lock.

只有当两个读者都释放了读写锁时,写入者才会获取锁。

最佳答案

仔细阅读联机帮助页。

注意你引用的句子

The calling thread acquires the read lock if a writer does not hold the lock and there are no writers blocked on the lock

是否表示,如果有写入者被阻止,则读取者将不会获取锁(if当且仅当

以下将使用POSIX文档。紧跟在引用的句子后面的段落指定了如果有写入者被锁阻塞时pthread_rwlock_rdlock()如何操作:

[TPS] [Option Start] If the Thread Execution Scheduling option is supported, and the threads involved in the lock are executing with the scheduling policies SCHED_FIFO or SCHED_RR, the calling thread shall not acquire the lock if a writer holds the lock or if writers of higher or equal priority are blocked on the lock; otherwise, the calling thread shall acquire the lock. [Option End]

[TPS TSP] [Option Start] If the Threads Execution Scheduling option is supported, and the threads involved in the lock are executing with the SCHED_SPORADIC scheduling policy, the calling thread shall not acquire the lock if a writer holds the lock or if writers of higher or equal priority are blocked on the lock; otherwise, the calling thread shall acquire the lock. [Option End]

If the Thread Execution Scheduling option is not supported, it is implementation-defined whether the calling thread acquires the lock when a writer does not hold the lock and there are writers blocked on the lock. If a writer holds the lock, the calling thread shall not acquire the read lock. If the read lock is not acquired, the calling thread shall block until it can acquire the lock. The calling thread may deadlock if at the time the call is made it holds a write lock.

因此,要提供完整的答案,您需要发布您的实现是否提供线程执行调度选项,如果提供,则选择哪种调度策略。

要查看当前的调度策略是什么(如果您使用的是 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);
}

除非当前的调度策略是 Round-Robin 或 Fifo,否则引用文档的前两段不适用。在这种情况下,调度行为是由实现定义的。特别是,读取器/写入器锁很容易优先选择读取器,在这种情况下,写入器几乎肯定永远不会为您的程序运行,因为读取器根据 C11 草案标准 n1570,在保护 stdout 的锁上进行序列化(通过 printf()):

7.21 Input/output

7.21.2 Streams

7 Each stream has an associated lock that is used to prevent data races when multiple threads of execution access a stream, and to restrict the interleaving of stream operations performed by multiple threads. Only one thread may hold this lock at a time. The lock is reentrant: a single thread may hold the lock multiple times at a given time.

由于持有该锁的同时也持有读锁,并且在持有读锁的同时执行了 sleep(),并且读取者在释放读锁和再次获取它之间不执行任何操作,因此在任何时候都没有读者持有锁的情况非常小。因此,作者永远没有机会。

关于c - pthread_rwlock的优先级?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55986628/

40 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com