linux——读写锁

1.读写锁是几把锁?

一把锁

pthread_rwlock_t lock;

2.读写锁的类型;

读锁-对内存做读操作

写锁-对内存做写操作

3.读写锁的状态

4.读写锁的特性:

线程A加读锁成功,又来了三个线程,做读操作,可以加锁成功

读共享-并行处理

线程A加写锁成功,又来了三个线程,做读操作,三个线程阻塞

写独占

线程A加读锁成功,又来了B线程加写锁阻塞,又来了C线程加读锁阻塞

读写不可以同时进行

写的优先级高

5.读写锁场景练习

线程A加写锁成功,线程B请求读锁

线程B阻塞

线程A持有读锁,线程B请求写锁

线程B阻塞

线程A拥有读锁,线程B请求读锁

线程B加锁

线程A持有读锁,然后线程B请求写锁,然后线程C请求读锁

线程B阻塞,线程C阻塞

线程B加锁,线程C阻塞

线程C加锁

线程A持有写锁,然后线程B请求读锁,然后线程C请求写锁

线程B阻塞,线程C阻塞

线程C加锁, 线程B阻塞

线程B加锁

6.读写锁的适用场景

互斥锁-读写串行

读写锁:

读:并行 写:串行

程序中的读操作 > 写操作的时候

7.主要操作函数

初始化读写锁

pthread_rwlock_init(pthread_rwlock_t* restrict rwlock, const pthread_rwlockattr_t* restrict attr ); 销毁读写锁

pthread_rwlock_destroy(pthread_rwlock_t* rwlock):

加读锁

pthread_rwlock_rdlock(pthread_rwlock_t* rdlock);

阻塞:之前对这把锁加的是写锁的操作

尝试加读锁

pthread_rwlock_tryrdlock(pthread_rwlock_t* rwlock);

加锁成功:返回0 失败:返回错误号

加写锁

pthread_rwlock_wrlock(pthread_rwlock_t* rwlock);

阻塞:上一次加写锁还没解锁 阻塞:上一次加读锁还没解锁

尝试加写锁

pthread_rwlock_trywrlock(pthread_rwlock_t* rwlock);

解锁

pthread_rwlock_unlock(pthread_rwlock_t* rwlock);

8.练习

三个线程不定时写同一个全局变量,五个线程不定时期读同一全局资源 先不加锁

复制代码
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>

int number = 0;

void* write_func(void *arg)
{
	while(1)
	{
		number++;
		printf("write:%ld,%d\n",pthread_self(),number);
		usleep(500);
	}
}
void* read_func(void *arg)
{
	while(1)
	{
		printf("read:%ld,%d\n",pthread_self(),number);
		usleep(500);
	}
}
int main()
{
	pthread_t p[8];

	for(int i=0;i<3;++i)
	{
		pthread_create(&p[i],NULL,write_func,NULL);
	}
	for(int i=3;i<8;++i)
	{
		pthread_create(&p[i],NULL,read_func,NULL);
	}

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

	return 0;
}

这段代码的问题:

  1. 3 个写线程 + 5 个读线程同时访问 number

  2. number++ 不是原子操作

  3. 读和写同时发生,会出现脏数据、重复数据、错乱数据

  4. 没有任何同步控制,线程自由竞争,数据不安全

现象:

  • 写线程在改

  • 读线程在读

  • 输出会乱、数字会跳、重复、甚至读到一半的值

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

    int number = 0;
    //create rwlock
    pthread_rwlock_t lock;

    void* write_func(void arg)
    {
    while(1)
    {
    pthread_rwlock_wrlock(&lock);
    number++;
    printf("write:%ld,%d\n",pthread_self(),number);
    pthread_rwlock_unlock(&lock);
    usleep(500);
    }
    }
    void
    read_func(void *arg)
    {
    while(1)
    {
    pthread_rwlock_rdlock(&lock);
    printf("read:%ld,%d\n",pthread_self(),number);
    pthread_rwlock_unlock(&lock);
    usleep(500);
    }
    }
    int main()
    {
    pthread_rwlock_init(&lock,NULL);
    pthread_t p[8];

    复制代码
      for(int i=0;i<3;++i)
      {
      	pthread_create(&p[i],NULL,write_func,NULL);
      }
      for(int i=3;i<8;++i)
      {
      	pthread_create(&p[i],NULL,read_func,NULL);
      }
    
      for(int i=0;i<8;++i)
      {
      	pthread_join(p[i],NULL);
      }
    
      pthread_rwlock_destroy(&lock);
    
      return 0;

    }

加了读写锁之后,就没有出现数据混乱的现象

读写锁版本

严格遵守 3 条黄金规则:

规则 1:写锁 == 独占锁

同一时间只能有一个写线程加锁

规则 2:读锁 == 共享锁

多个读线程可以同时加锁(5 个读线程可以一起读)

规则 3:写与读互斥

  • 有写锁,读锁必须等待

  • 有读锁,写锁必须等待

相关推荐
AnalogElectronic42 分钟前
linux 测试网络和端口是否连通的命令详解
linux·网络·php
Edward111111111 小时前
4月28日防火墙问题
linux·运维·服务器
子琦啊2 小时前
【算法复习】字符串 | 两个底层直觉,吃透高频题
linux·运维·算法
AOwhisky3 小时前
Kubernetes 学习笔记:集群管理、命名空间与 Pod 基础
linux·运维·笔记·学习·云原生·kubernetes
小龙在慢慢变强..4 小时前
目录结构(FHS 标准)
linux·运维·服务器
2035去旅行4 小时前
嵌入式开发,如何选择C标准库
linux·arm开发
刘延林.4 小时前
win11系统下通过 WSL2 安装Ubuntu 24.04 使用RTX 5080 GPU
linux·运维·ubuntu
CodeOfCC5 小时前
Linux 嵌入式arm64安装openclaw
linux·运维·服务器
宵时待雨6 小时前
linux笔记归纳3:linux开发工具
linux·运维·笔记
magrich6 小时前
安装NoMachine并解决无外接显示器桌面黑屏
linux·运维·服务器