C语言queue如何加锁和解锁

C语言queue如何加锁和解锁,第1张

有两种办法:

重载一个queue模板,把锁封装到重载的函数

每次使用queue的函数的时亩誉候加迅粗段锁,使凳蔽用完毕后,解锁

读写锁(readers-writer)是计算机程序并发控制的一种同步机制,用于解决读写问题。

当多个线程并行访问共享资源时,有些线程执行读 *** 作、有些线程执行写 *** 作,这时会出现读写问题。多个线程同时读共享资源不会出现问题,但有线程写时其他线程必须等待,否则会损坏数据。

读写锁允许并行读、串行写。与互斥锁的一次只有一个线程执行 *** 作相比,性能更高。比如构建缓存系统,将网络资源写入缓存,后期从缓存读取资源。缓存系统必须线程安全,允许并行读取,串行写入。

这篇文章将介绍 pthread_rwlock_t 和 dispatch barrier 两种实现读写锁的方案。

pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) 函数使用 attr 属性初始化 rwlock 读写锁。如果 attr 为 nil,则使用默认属性初始凯燃化读写锁。

初始化后 rwlock 可以使用任意次数。初始化已经初始化的 rwlock,会产生无法预期的后果。使用未初始化的 rwlock,会产生无法预期的后果。

pthread_rwlock_t 初始化方法如下:

pthread_rwlock_rdlock() 函数为读写锁添加读锁。如果没有写锁已经加锁、队列中也没有写锁,该函数为读写锁添加读锁。如果读写锁未被写锁加锁,且队列中有写锁时,无法确定 pthread_rwlock_rdlock() 是否会加锁。如果写锁已经加锁,则 pthread_rwlock_rdlock() 函数不会伏蔽捕获读写锁。如果读锁未能捕获读写锁,则线程会堵塞在 pthread_rwlock_rdlock() ,直到读锁加锁成功。如果当前线程已经添加了写锁,再次调用 pthread_rwlock_rdlock() 函数结果将无法定义。

一个线程可以同时多次持有读锁,解锁时需调用对应次数的 pthread_rwlock_unlock() 。

pthread_rwlock_tryrdlock() 函数像 pthread_rwlock_rdlock() 函数一样添加读锁,但当有写锁持有、等待读写锁时,则会直接失败。

pthread_rwlock_wrlock() 函数将读写锁锁定为写状态。如果当前没有线程(包括读锁、写锁)持有读写锁,写锁加锁成功。否则,会堵塞线程直到成功。如果当前线程(包括读锁、写锁)已经持有读写锁,再次调用写锁会导致无法预期的结果。

pthread_rwlock_trywilock() 函数与 pthread_rwlock_wrlock() 相似,但当有线程(包括读锁、写锁)持有读写锁时, pthread_rwlock_trywilock() 函数会立即返回错误。

pthread_rwlock_unlock() 函数用于解锁读写锁。如果线程没有持有读写锁,调用 pthread_rwlock_unlock() 会产生无法预期的错误。

调用 pthread_rwlock_unlock() 函数解锁读锁后,如果还有其他读锁持有读写锁,则读写锁仍处于读状态。如果 pthread_rwlock_unlock() 函数释放了当前线程的最后一个读锁,则当前线程不再是该读写锁的持有者。如果 pthread_rwlock_unlock() 释放了最后一个读锁,则读写锁进入未加锁状态。

调用 pthread_rwlock_unlock() 函数缺孙州解锁写锁后,读写锁进入未加锁状态。

如果调用 pthread_rwlock_unlock() 函数后锁进入未加锁状态,同时有多个线程等待添加写锁,调度策略决定哪个线程获取写锁。如果有多个线程等待添加读锁,调度策略决定线程进入顺序。如果多个线程等待添加读锁、写锁,则无法确定是读锁还是写锁先加锁。

pthread_rwlock_destroy() 函数销毁读写锁,及读写锁使用的资源。销毁后可以使用 pthread_rwlock_init() 再次初始化锁,任何其他方式使用已销毁的锁都会产生无法预期的后果。

当读写锁处于加锁状态时,调用 pthread_rwlock_destroy() 会产生无法预期的后果。销毁未初始化的锁,会产生无法预期的后果。

GCD 提供、管理执行任务的队列。这种抽象隐藏了线程管理,开发者只需专注于构建任务序列。

在保护临界区域时,GCD 提供了 dispatch barrier。当执行 barrier 任务时,队列中所有其他任务都会等待。没有执行 barrier 任务时,其他任务并行执行。

Dispatch barrier 必须用在自定义并发队列中。如果用在全局队列中,将起不到屏障作用。串行队列一次执行一个任务,无需使用 barrier。

创建并发队列方法如下:

Dispatch barrier 使用 dispatch_barrier_async 和 dispatch_barrier_sync 函数控制写 *** 作。上述函数和 dispatch_sync 和 dispatch_async 类似,独特之处在于用在自定义并发队列时,使用 barrier 函数提交的任务串行执行,并且会等待当前执行中的任务执行完毕才开始。当 barrier 任务执行完毕后,恢复并行执行。

串行序列没有必要使用 barrier 函数,因为串行序列本身一次只会执行一个任务。由于系统也在使用全局队列,barrier 会堵塞其他任务执行,因此在全局队列中使用 barrier 将起不到屏障作用。此时,效果完全等价于 dispatch_sync 和 dispatch_async 。

使用 barrier 后可以确保只有一个线程进入临界区域,确保线程安全。

使用 sync 函数直接读锁即可:

Demo名称:Synchronization

源码地址: https://github.com/pro648/BasicDemos-iOS/tree/master/Synchronization

参考资料:

欢迎更多指正: https://github.com/pro648/tips

本文地址: https://github.com/pro648/tips/blob/master/sources/线程同步之读写锁.md

#include"stdio.h"

main()

{

int x

char a

printf("蚂镇input a number:\n")

scanf("%d",&x)

fflush(stdin) //添加仿冲

printf("input a char:\n")

scanf("%c"备物歼,&a)

printf("%d,%c",x,a)

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11996114.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-20
下一篇 2023-05-20

发表评论

登录后才能评论

评论列表(0条)

保存