如果我有一个线程写入和多个读取,我如何只在写入时锁定而不是读取?
Posted
技术标签:
【中文标题】如果我有一个线程写入和多个读取,我如何只在写入时锁定而不是读取?【英文标题】:If I have one thread writing and many reading, how can I only lock when writing, but not reading? 【发布时间】:2015-11-26 19:30:17 【问题描述】:所以我有这个结构到我正在写的缓存:
struct scache
char* rp;
int ce;
char* code;
struct headers* headers;
struct body* body;
;
struct dcache
unsigned char md5[16];
struct scache scache;
;
struct cache
struct scache** scaches;
size_t scache_size;
struct dcache** dcaches;
size_t dcache_size;
;
struct scache* getSCache(struct cache* cache, char* rp, int ce);
struct dcache* getDCache(struct cache* cache, char* rp, int ce, unsigned char* md5);
int addSCache(struct cache* cache, struct scache* scache);
int addDCache(struct cache* cache, struct dcache* dcache);
我想使用互斥锁,这样我在写作时就不能允许任何读取,但不会让读取阻塞其他读取。所以读线程不会互相阻塞,但是如果一个加一个,就会阻塞其他的读写。
我研究了互斥体,但我不知道如何实现这一权利。我想我可以锁定写入,但是如果读取看到的大小比实际大小更大或更小,然后读取不足或过度读取,都会导致双重缓存或内存损坏问题。
【问题讨论】:
您可以使用_Atomic
和stdatomic.h
(C11 起)。比互斥锁等更轻量级,但实现起来可能更复杂,具体取决于实际数据类型。
请注意,读取也必须是原子的。这很可能需要针对中间写入进行锁定。更不用说编译器和/或硬件对指令/内存访问重新排序等其他问题了。
@Olaf 原子性和读写锁定是两个完全不同的概念。如果可用,正确实现读写锁将使用原子操作。
@Let_Me_Be:我没有说它们是相同的,但它们可能是相关的,虽然现代 CPU 为基本类型提供原子读/写,但它们需要更多的复合数据类型。并且还有锁定的替代方法,例如具有硬件支持的更改检测的独占访问,例如 ARMs LDREX/STREX 指令。但是,有时锁定比重试更有效。一切都取决于实际使用情况,例如访问频率。请注意,实际上有两个级别的原子访问。硬件/低级和更复杂的结构。
【参考方案1】:
你想要的是一个读写锁。根据偏向的方式,有不同的实现方式。
两个边界极端是:
写入可立即访问 只有在有 0 个读取等待时写入才能访问大多数实现都偏向写入或读取。
有关标准 POSIX 实现,请参阅:pthread_rwlock_t
http://pubs.opengroup.org/onlinepubs/007908799/xsh/pthread_rwlock_init.html
【讨论】:
以上是关于如果我有一个线程写入和多个读取,我如何只在写入时锁定而不是读取?的主要内容,如果未能解决你的问题,请参考以下文章