- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
考虑这个示例代码:
#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/
int x = 1; System.out.println( x++ + x++ * --x ); 上面的代码打印出“5”,但我不明白怎么办?我一直为最后一个 x 取零,然后乘以仍然为 0 的第二个
我现在正在尝试使用 Preference 类 首选项 pfrOfThis = Preferences.userNodeForPackage(this) 出现错误: “类 java.util.prefs
用下面的代码 import sys print "Hello " + sys.argv[1] if len(sys.argv) > 1 else "Joe" + "." 当我运行时 python he
我的网页包含: td { padding-left:10px; } 引用的样式表包含: .rightColumn * {margin: 0; padding: 0;} 我在 rightc
使用 JPA 我有一个关于 CascadeTypes 的问题。 例如: @ManyToMany(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST,
下面的“括号”是怎么写的? val words = List("foo", "bar", "baz") val phrase = "These are upper case: " + words ma
我只是想知道,对于以下代码,编译器是否单独使用关联性/优先级或其他一些逻辑来评估。 int i = 0, k = 0; i = k++; 如果我们根据关联性和优先级进行评估,postfix ++具有比
我设置了一个 Azure FrontDoor 服务,以主/备份类型的方式将流量分配给两个 API 管理服务。就像我希望所有流量都流向我的主要 APIM 服务一样,如果我碰巧关闭该服务(假装中断),那么
这是一个简单的 CSS: /* Smartphones (portrait and landscape) ----------- */ @media only screen and (min-devi
我设置了一个 Azure FrontDoor 服务,以主/备份类型的方式将流量分配给两个 API 管理服务。就像我希望所有流量都流向我的主要 APIM 服务一样,如果我碰巧关闭该服务(假装中断),那么
来自 Programming Perl pg 90,他说: @ary = (1, 3, sort 4, 2); print @ary; 排序右侧的逗号在排序之前求值,而左侧的逗号在排序之
+----+------------+------+ | id | title | lang | +----+------------+------+ | 1 | title 1 EN |
如何使用 Java 获取 DiffServe 代码点 (DSCP) 整数的优先级部分?我预计它涉及位移位,但由于某种原因,我似乎无法获得我期望的值。 最佳答案 假设我理解正确,只需向右执行 3 位逻辑
我有下一个运行良好的 js 函数: $(function () { $(".country").click(function () { var countries = Arra
int a[3]={10,20,30}; int* p = a; cout << *p++ << endl; 根据 wikipedia ,后缀++的优先级高于解引用,*p++应该先运行p++再解引用结
我想在优先读取归档后解决这种类型的表达式 2+3/5*9+3-4 这是我尝试解决该任务的代码我该如何解决这个问题 while ( !inputFile.eof() ) { getline( inp
我正在玩 Rhino 并注意到这种奇怪的行为似乎是运算符优先级: js> {}+{} NaN js> ''+{}+{} [object Object][object Object] js> ''+({
我想遍历文件列表并检查它们是否存在,如果文件不存在则给出错误并退出。我写了下面的代码: FILES=( file1.txt file2.txt file3.txt ) for file in ${FI
我正在执行级联 SELECT: SELECT * FROM x WHERE a = 1 AND b = 2 AND c = 3 => If nothing found, try: SELECT * F
即将参加考试,我正在参加之前的考试。 问题: 当两个或多个样式表规则应用于同一元素时,以下哪种类型的规则将优先? 一个。任何来自浏览器的声明 b.有用户来源的正常声明 C。作者来源正常声明 d.文档级
我是一名优秀的程序员,十分优秀!