考虑此示例代码:
<?php
$kodsorgu = mysqli_query($con,"SELECT kod FROM kodlar ORDER BY RAND() LIMIT 1");
while($sam=mysqli_fetch_array($kodsorgu))
{
echo '<center>'.$sam['kod'].'</center>';
}
$deleted_code = $sam['kod'];
$sil = mysqli_query($con,"DELETE FROM kodlar WHERE kod = '$deleted_code'");
?>
我有一个线程在func1中循环,其中请求写锁定1秒钟,另外3个线程在func 2中循环,其中,请求读锁定1秒钟。
在pthread_rwlock_rdlock手册页上说:“如果写者不持有该写锁定并且没有写者被阻塞,则调用线程将获得读锁定。”从第5行的输出粘贴中,您可以在“ func 1:尝试锁定”中看到一个作家显然在那儿,所以为什么我的读者无论如何都会获得锁定?第5行之后,每秒打印3行。减少我的读者线程会增加作家获得锁定的机会。
#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);
}
}
添加了另一个示例
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;
}
根据pthread_rwlock_rdlock的联机帮助页,读取器2不应获取锁,因为存在具有相同优先级的写入器处于保留状态,并且所有线程的调度策略都设置为SCHED_RR(2)。
如果支持“线程执行计划”选项,并且 锁中涉及的线程正在按调度执行 策略SCHED_FIFO或SCHED_RR,则调用线程不得获取 如果作家持有锁,或者如果作家的等级更高或相等,则该锁 优先级被锁定;否则,调用线程应 获取锁。
仅当两个阅读器都释放了rw锁时,写入者才获得该锁。
答案 0 :(得分:1)
仔细阅读手册页 。
请注意,您引用的句子
如果写入者未持有该写入者并且锁上没有任何写入者,则调用线程将获得读取锁定
不说,如果有 个作家被阻止(if
而不是{{ 1}}。
以下内容将使用POSIX文档。
引用句子后面的段落指定了if and only if
的行为,如果被的作者锁死了:
[TPS] [Option Start]如果支持“线程执行调度”选项,并且 锁中涉及的线程正在按调度执行 策略SCHED_FIFO或SCHED_RR,则调用线程不得获取 如果作家持有锁,或者如果作家的等级更高或相等,则该锁 优先级被锁定;否则,调用线程应 获取锁。 [选项结束]
[TPS TSP] [选项开始]如果“线程执行计划”选项为 支持,并且锁中涉及的线程正在使用 SCHED_SPORADIC调度策略,调用线程不得获取 如果作家持有锁,或者如果作家的等级更高或相等,则该锁 优先级被锁定;否则,调用线程应 获取锁。 [选项结束]
如果不支持“线程执行计划”选项,则为 实现定义了调用线程是否获取锁 当作家没有持有锁并且有作家被封锁时 锁。如果写者持有该锁,则调用线程不应 获取读锁。如果未获取读锁,则调用 线程将阻塞直到可以获取锁为止。调用线程 如果在进行调用时它持有写锁,则可能会死锁。
因此,要提供完整的答案,将需要您发布实现是否提供了“线程执行调度”选项,如果提供,则选择了哪种调度策略。
要查看当前的调度策略是什么(如果您使用的是Linux),请运行以下程序:
pthread_rwlock_rdlock()
除非当前的调度策略是Round-Robin或Fifo,否则引用的文档的前两段均不适用。在这种情况下,调度行为是实现定义的。尤其是,读取器/写入器锁定很容易首选读取器,在这种情况下,写入器几乎肯定会永远不会运行您的程序,因为读取器正在按照C11草案标准n1570在保护#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);
}
的锁上进行序列化(通过stdout
)。
7.21输入/输出
7.21.2流
7每个流都有一个关联的锁,该锁用于防止多个执行线程访问一个流时的数据争用,并限制由多个线程执行的流操作的交织。一次只能有一个线程持有此锁。该锁是可重入的:单个线程可以在给定时间多次持有该锁。
由于此锁定在按住readlock的同时被保持,并且printf()
在按住readlock的同时也被执行,因此读者在释放readlock和重新获取readlock之间不会做任何事情,这可能是因为是没有读者拿着锁的很小。因此,作家永远没有机会。