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:写与读互斥

  • 有写锁,读锁必须等待

  • 有读锁,写锁必须等待

相关推荐
feng_you_ying_li43 分钟前
linux之网络层
linux·运维·网络
未来之窗软件服务1 小时前
Linux 运维日志删除的多种方式—东方仙盟
linux·运维·服务器·仙盟创梦ide·东方仙盟
小雉系统1 小时前
BcoreOS实战:用一个升级包,让Rocky Linux跑进Debian服务器
linux·运维·服务器·debian
thethefighter1 小时前
快速预览Word、WPS秒开,支持空格弹窗
linux·word·wps·快速预览·空格弹窗·nhdeepview
用户8351414049492 小时前
把日志和寄存器值喂给AI做故障定位,我的实际问法
linux·ubuntu
Ruiery2 小时前
Linux 6.6内核内存管理深度解析(十七):vmalloc — 内核要“虚拟连续“就够:物理页逐个凑,页表来连
linux·运维·服务器
Escalating_xu2 小时前
【Linux 网络编程】ARP 的具体过程与 ARP 欺骗:一条 IP → MAC 映射,怎样改变数据的去向?
linux·网络·tcp/ip
坚定的共产主义生产设备永不宕机2 小时前
服务器从裸机开始搭建ESXI虚拟机
linux·服务器·网络
刚入门的大一新生2 小时前
Linux-线程封装
linux·运维·服务器
god_cvz3 小时前
实践:Linux环境构建CTB工具(cesium-terrain-builder)
linux·gis·ctb