【linux编程】读写锁

读写锁

读写锁由「读锁」和「写锁」两部分构成,如果只读取共享资源用「读锁」加锁,如果要修改共享资源则用「写锁」加锁。所以,读写锁适用于能明确区分读操作和写操作的场景。

读写锁的工作原理是:

  • 当「写锁」没有被线程持有时,多个线程能够并发地持有读锁,这大大提高了共享资源的访问效率,因为「读锁」是用于读取共享资源的场景,所以多个线程同时持有读锁也不会破坏共享资源的数据。
  • 但是,一旦「写锁」被线程持有后,读线程的获取读锁的操作会被阻塞,而且其他写线程的获取写锁的操作也会被阻塞。

所以说,写锁是独占锁,因为任何时刻只能有一个线程持有写锁,类似互斥锁和自旋锁,而读锁是共享锁,因为读锁可以被多个线程同时持有。知道了读写锁的工作原理后,我们可以发现,读写锁在读多写少的场景,能发挥出优势。

另外,根据实现的不同,读写锁可以分为「读优先锁」和「写优先锁」。

读优先锁期望的是,读锁能被更多的线程持有,以便提高读线程的并发性,它的工作方式是:当读线程 A 先持有了读锁,写线程 B 在获取写锁的时候,会被阻塞,并且在阻塞过程中,后续来的读线程 C 仍然可以成功获取读锁,最后直到读线程 A 和 C 释放读锁后,写线程 B 才可以成功获取读锁。如下图:

 

 而写优先锁是优先服务写线程,其工作方式是:当读线程 A 先持有了读锁,写线程 B 在获取写锁的时候,会被阻塞,并且在阻塞过程中,后续来的读线程 C 获取读锁时会失败,于是读线程 C 将被阻塞在获取读锁的操作,这样只要读线程 A 释放读锁后,写线程 B 就可以成功获取读锁。如下图:

 

 

 

归纳总结:

 

 1. 函数原型:

#include <pthread.h>
pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);  // 初始化读写锁
pthread_rwlock_destroy(pthread_rwlock_t *rwlock);    // 销毁读写锁

2. 函数原型:

#include <pthread.h>
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); // 读锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);  // 写锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); // 解锁

 

1.实例:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

int h = 10000;

pthread_rwlock_t lock; //创建 读写锁

void *funwrite(void *arg)
{
  while (10)
  {
    for (int i = 0; i < 10000; i++)
    {
      pthread_rwlock_wrlock(&lock); //加写锁
      h++;
      printf("write is %d\n", h);
      pthread_rwlock_unlock(&lock); //解锁
      
      sleep(2);
    }
  }
}

void *funread(void *arg)
{
  while (10)
  {
    for (int i = 0; i < 10000; i++)
    {
      pthread_rwlock_rdlock(&lock); //加读锁
      printf("read is %d\n", h);
      pthread_rwlock_unlock(&lock); //解锁

      sleep(3);
    }
  }
}

int main()
{
  pthread_t p[8];
  int i;
  pthread_rwlock_init(&lock, NULL); // 初始化读写锁

  for (i = 0; i < 3; i++)
    pthread_create(&p[i], NULL, funwrite, NULL);

  for (i = 3; i < 8; i++)
    pthread_create(&p[i], NULL, funread, NULL);

  for (int a = 0; a < 8; a++)
    pthread_join(p[a], NULL);

  pthread_rwlock_destroy(&lock); // 销毁

  return 0;
}

输出:

 

 

参考资料

1. 面试官:你说说互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景

posted @ 2022-04-12 22:51  苏格拉底的落泪  阅读(363)  评论(0编辑  收藏  举报