当前位置: 首页 > ai >正文

Linux线程——锁

一.原子操作

CPU处理一个指令,进程/线程 在处理完这个指令之前是不会失去CPU的
就像原子被认为是不可分割颗粒一样

如下代码是没有加锁的,就会可能因为cpu抢占问题在执行到一般的代码的时候不能往下执行,再次得到cpu的时候又重新执行造成混乱。

void* procucer(void * arg)
{
while(1){//创建一个链表的节点Node * newNode = (Node*)malloc(sizeof(Node));//initnewNode‐>data = rang()%100;newNode ‐>next = head;head = newNode;printf("+++product:%d\n",newNode‐>data);sleep(rang()%3);}
reutn NULL;
}

这个个代码就加上了互斥锁就不会出现混乱的问题

//示例代码2:
void* procucer(void * arg)
{while(1){//创建一个链表的节点Node * newNode = (Node*)malloc(sizeof(Node));//initnewNode‐>data = rang()%100;//加锁pthread_mutex_lock(&mutex);newNode ‐>next = head;head = newNode;printf("+++product:%d\n",newNode‐>data);//解锁pthread_mutex_unlock(&mutex);sleep(rang()%3);}reutn NULL;
}

二.死锁

造成死锁的原因:
1.自己锁自己

如下面代码加了两把锁,将自己锁在了第二把锁哪里

操作做完之后,一定要解锁 

for(int i = 0;i<MAX;i++)
{
pthread_mutex_lock(&mutex);
pthread_mutex_lock(&mutex);//被阻塞在了这里int crt = number;
crt++;
number = crt;
printf("thread A id = %ld,number = %d\n",pthread_self(),number);pthread_mutex_unlock(&mutex);
usleep(10);
}

2.

线程1 对共享资源A加锁成功-A锁
线程2 对共享资源B加锁成功-B锁


线程1访问共享资源B,对B锁加锁-线程1阻塞在B锁上
线程2访问共享资源A,对A锁加锁-线程2阻塞在A锁上


如何解决:
-让线程按照一定的顺序去访问共享资源
-在访问其他锁的时候,需要先将自己的锁解开
--try_lock,用try_lock加锁失败也不会堵塞

三.读写锁

1.读写锁是几把锁?

一把锁
pthread_rwlock_t lock;

2.读写锁的类型;

读锁-对内存做读操作
写锁-对内存做写操作

3.读写锁的状态


4.读写锁的特性:

线程A加读锁成功,又来了三个线程,做读操作,可以加锁成功
        读共享-并行处理
线程A加写锁成功,又来了三个线程,做读操作,三个线程阻塞
        写独占
线程A加读锁成功,又来了B线程加写锁阻塞,又来了C线程加读锁阻塞
        读写不可以同时进行
        写的优先级高

5.读写锁场景练习

线程A加写锁成功,线程B请求读锁
        线程B阻塞,A写锁优先级高,写完才能B读


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


线程A拥有读锁,线程B请求读锁
        线程B加锁,读可以共享资源


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


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

写锁优先级高,所以A写完到C才到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)

四.练习:

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

发现read:13459、13461,但是write的时候又变成13460,这是因为没有加锁

加读写锁之后就不会出现那种情况

http://www.xdnf.cn/news/368.html

相关文章:

  • 四级英语题型分析
  • 全链路灰度实现
  • 从FPGA实现角度介绍DP_Main_link主通道原理
  • 递归下降 ll(1) 型文法 识别二元组文法分析
  • libevent的bufferevent测试用例和使用方法(附带源码)
  • 筛选法(埃氏筛法)C++
  • 聊聊Doris的数据模型,如何用结构化设计解决实时分析难题
  • 【Linux我做主】make和makefile自动化构建
  • Python语法系列博客 · 第3期 数据结构入门(列表、元组、字典、集合)
  • LeetCode 239 滑动窗口最大值
  • 【深度学习—李宏毅教程笔记】Transformer
  • 探索 .bat 文件:自动化任务的利器
  • 关于数字信号与图像处理——基于Matlab的图像增强技术
  • 将软件架构风格定义为数据流风格,调用返回风格,独立构件风格,虚拟机风格和以数据为为中心这五种风格的依据是什么?请介绍这五种风格
  • 区块链木材业务服务平台:商贸物流新变革
  • 模态双侠闯江湖:SimTier 分层破局,MAKE 智炼新知
  • 不确定与非单调推理的可信度方法
  • 【C++算法】67.栈_基本计算器 II
  • IntelliJ IDEA右键快捷方式设置方法
  • 从 LabelImg 到 Label Studio!AI 数据标注神器升级,Web 版真香
  • 8 编程笔记全攻略:Markdown 语法精讲、Typora 编辑器全指南(含安装激活、基础配置、快捷键详解、使用技巧)
  • VsCode搭建
  • Spring Boot + Caffeine:打造高性能缓存解决方案
  • 2.凸包优化求解
  • Viewer.js的使用方法
  • JDBC 数据库连接全解析:从驱动配置到工具类封装
  • yolov8的数据处理lableimg的安装以及使用
  • 黑马商城(五)微服务保护和分布式事务
  • 【Linux篇】探索进程间通信:如何使用匿名管道构建高效的进程池
  • PHP实现简单的爬虫功能