一 回顾
1 互斥锁在上节 详细介绍了 他可以解决在同步线程发生抢占时 导致的数据混乱
2 同时也解释了 进行同步线程会出现的原因 1 cpu的占用权
2 数据混乱
二 读写锁 概念
读写锁是一把锁 不是两把
三 读写锁的特征
画图 介绍一下
第二个情况
1 首先知道并行的概念 它指的是一个时间段同步执行
2 因为cpu读取很快 所以会 看到是一起的其实不是
因为读写不可同时执行 只能写释放之后 才可以读
读写不可同时进行 但是读可以实现 并发
写是读被阻塞等待的 只能当读释放了 写才可以解除阻塞等待
总的来说
读写锁:读 可以并发 写 只能并行
比如 线程AB 为加读锁 剩下为写锁
读可并发 写只能并行(轮流进行)
四 读写锁函数
其实 篮筐圈的 和 互斥锁类似函数的功能就是一样的解释 没什么好说的
初始化读写锁 一个参数 取 定义读写锁的变量地址 第二个和线程创建属性相关 直接NULL
无需属性。
销毁锁的功能 就是不用的时候 就销毁
参数就是一个 取读写锁的地址 即可
五 应用实战
先不加读写锁
#include <stdio.h>
#include<pthread.h>
#include <stdlib.h>
int h=0;
void *funwrite(void *arg)
{
while(12)
{
for(int i=0;i<10000;i++)
{
h++;
printf("write is %d\n",h);
usleep(1000);
}
}
}
void *funread(void *arg)
{
while(12)
{
for(int i=0;i<10000;i++)
{
printf("write is %d\n",h);
usleep(1000);
}
}
}
int main()
{
pthread_t p[8];
int i;
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); //回收
}
return 0;
}
注意 这里 虽然写线程是五个 但是他们都是进行一个事情 所以一个就够了
读也是如此
读写发生混乱了
读的时候已经是 上一次的数据
但是现在不是
需要加入读写锁解决
#include <stdio.h>
#include<pthread.h>
#include <stdlib.h>
int h=10000;
pthread_rwlock_t lock; //创建 读写锁
void *funwrite(void *arg)
{
while(12)
{
for(int i=0;i<10000;i++)
{
ptread_rwlock_wrlock(&lock);//加写锁
h++;
printf("write is %d\n",h);
ptread_rwlock_unlock(&lock); //解锁
usleep(1000);
}
}
}
void *funread(void *arg)
{
while(12)
{
for(int i=0;i<10000;i++)
{
ptread_rwlock_rwlock(&lock); //加读锁
printf("write is %d\n",h);
ptread_rwlock_unlock(&lock); //解锁
usleep(1000);
}
}
}
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;
}
写顺序正常
读也正常