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

线程互斥与线程同步

目录

线程互斥

一、概念补充

二、互斥锁(pthread_mutex_t)

线程同步

一、概念介绍

二、cond接口

三、生产者与消费者模型(“321”原则)


线程互斥

一、概念补充

1.临界资源

被保护起来的共享资源就是临界资源

2.原子性

原子性是指一个操作或一组操作在执行过程中是不可分割的,即这些操作要么全部执行成功,要么全部不执行,不存在中间状态。这种特性确保了数据的一致性和完整性,避免了因操作被部分执行而导致的错误或不一致。

二、互斥锁(pthread_mutex_t)

1.申请锁的过程必须是原子的

<1>申请成功:继续向后运行,访问临界区的代码,访问临界资源

<2>申请失败:阻塞挂起,申请执行流

2.锁提供能力的本质

执行临界区代码,并由并行转为串行

3.锁的原理

<1>硬件级实现,关闭时钟中断

<2>软件级实现:为实现互斥锁操作,大多数体系结构都提供了swap或exchange指令,该指令的作用是将寄存器和内存单元的数据进行交换

补:如果把一个变量的内容交换到CPU寄存器内部,本质上是将该变量的内容获取到当前执行流的硬件上下文中

4.锁的作用

最基本的同步机制,确保同一时间只有一个线程持有锁

5.互斥锁既可以用类型pthread_mutex_t来定义,也可以使用函数来定义

<1>初始化锁:

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);

1)头文件:#include<pthread.h>

2)功能:初始化锁

3)参数:

mutex是指向互斥锁变量的指针;

attr是指向互斥锁属性的指针,通常设置为NULL以使用默认属性

4)返回值:成功返回不为0的值,失败返回0

<2>销毁锁:int pthread_mutex_destroy(pthread_mutex_t *mutex);

1)头文件:#include<pthread.h>

2)功能:销毁锁

3)参数:mutex是指向互斥锁变量的指针;

4)返回值:成功返回不为0的值,失败返回0

<3>加锁:int pthread_mutex_lock(pthread_mutex_t *mutex);

注:加锁时尽量让范围颗粒度尽可能的细,尽量不要包含太多的非临界区

1)头文件:#include<pthread.h>

2)功能:加锁

3)参数:mutex是指向互斥锁变量的指针;

4)返回值:成功返回不为0的值,失败返回0

<4>解锁:int pthread_mutex_unlock(pthread_mutex_t *mutex);

1)头文件:#include<pthread.h>

2)功能:解锁

3)参数:mutex是指向互斥锁变量的指针;

4)返回值:成功返回不为0的值,失败返回0

6.加锁之后,在临界区内部允许线程切换吗?

允许线程切换。由于当前线程并未释放锁,是持锁切换,即使它不在,其他线程也要等它回来执行完代码,释放锁,其他线程才能展开锁的竞争进入临界区

线程同步

一、概念介绍

在多线程编程中,线程同步(Thread Synchronization)是解决多线程并发执行时共享资源访问冲突的核心机制。其核心目标是确保多个线程在访问共享数据或执行关键操作时能够按照预期的顺序和规则进行,避免数据竞争(Data Race)、死锁(Deadlock)等并发问题。

二、cond接口

1.int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);

<1>头文件:#include<pthread.h>

<2>功能:初始化条件变量

<3>参数:

cond:指向条件变量的指针;

attr:条件变量属性,通常设为NULL使用默认属性。

<4>返回值:成功返回不为0的值,失败返回0

2.int pthread_cond_destroy(pthread_cond_t *cond);

<1>头文件:#include<pthread.h>

<2>功能:销毁条件变量,释放相应资源

<3>参数:cond:指向条件变量的指针;

<4>返回值:成功返回不为0的值,失败返回0

3.int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

<1>头文件:#include<pthread.h>

<2>功能:阻塞当前线程,直至被其他线程唤醒

<3>参数:

cond:指向条件变量的指针;

mutex:与条件变量关联的互斥锁(必须在调用前已加锁)。

<4>返回值:成功返回不为0的值,失败返回0

4.int pthread_cond_signal(pthread_cond_t *cond);

<1>头文件:#include<pthread.h>

<2>功能:唤醒一个在等待在条件变量上的线程

<3>参数:cond:指向条件变量的指针;

<4>返回值:成功返回不为0的值,失败返回0

5.int pthread_cond_broadcast(pthread_cond_t *cond);

<1>头文件:#include<pthread.h>

<2>功能:唤醒所有在等待在条件变量上的线程

<3>参数:cond:指向条件变量的指针;

<4>返回值:成功返回不为0的值,失败返回0

三、生产者与消费者模型(“321”原则)

1.3种关系:

生产者之间:竞争关系/互斥关系;

消费者之间:竞争关系/互斥关系;

生产者和消费者之间:互斥关系,同步关系

2.2种角色:生产者和消费者(由线程承担)

3.1个交易场所(一种临界资源):以特定结构构成的一个“内存”空间

4.为什么要有生产者与消费者模型?/有什么好处?

<1>生产过程和消费过程解耦

<2>支持忙闲不均

<3>提高效率(体现在为获取任务和处理任务时是并发的)

5.实例介绍:基于阻塞队列(blockqueue)的生产者与消费者模型

仍遵循“先进先出”的原则,但是当队列为空时从队列中获取元素时会被阻塞,直至队列中被放入元素

6.代码呈现

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>#define BUFFER_SIZE 10
int buffer[BUFFER_SIZE];
int count = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;void* producer(void* arg) {for (int i = 0; i < 20; i++) {pthread_mutex_lock(&mutex);while (count == BUFFER_SIZE) {pthread_cond_wait(&cond, &mutex); // 缓冲区满,等待}buffer[count++] = i;printf("Produced: %d\n", i);pthread_cond_signal(&cond); // 通知消费者pthread_mutex_unlock(&mutex);}return NULL;
}void* consumer(void* arg) {for (int i = 0; i < 20; i++) {pthread_mutex_lock(&mutex);while (count == 0) {pthread_cond_wait(&cond, &mutex); // 缓冲区空,等待}int item = buffer[--count];printf("Consumed: %d\n", item);pthread_cond_signal(&cond); // 通知生产者pthread_mutex_unlock(&mutex);}return NULL;
}int main() {pthread_t prod, cons;pthread_create(&prod, NULL, producer, NULL);pthread_create(&cons, NULL, consumer, NULL);pthread_join(prod, NULL);pthread_join(cons, NULL);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);return 0;
}

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

相关文章:

  • HTML入门教学
  • 不同类型的 SAP 项目
  • 零件画图实战提升案例(下)
  • 7系列 之 I/O标准和终端技术
  • 2.商户查询缓存
  • 时钟晶振锁相环pll方向技术要点和大厂题目解析
  • MRNet 数据集分享
  • 流式数据(Streaming Data)和非流式数据(Batch Data)区别、使用场景、优化-来自前端的浅解
  • 微机控制电子式持久蠕变慢应变应力腐蚀试验机
  • sh脚本多卡顺序执行训练文件
  • C++中线程安全的对多个锁同时加锁
  • C++STL在算法竞赛中的应用详解
  • 推理还原的干货
  • MySQL索引使用规则详解:从设计到优化的完整指南
  • 深度学习全流程解析
  • linux 开发小技巧之git增加指令别名
  • 树莓派4的v4l2摄像头(csi)no cameras available,完美解决
  • 让人类和人造智能体更好的感知世界 千眼狼ACE高速摄像机发布
  • 【数据结构入门训练DAY-30】数的划分
  • JVM 数据区域
  • python:vars()方法
  • 2025年渗透测试面试题总结-渗透测试红队面试四(题目+回答)
  • 免费 无需安装 批量图片压缩 高压缩比与画质保留软件
  • 【验证哥德巴赫猜想(奇数)】2021-11-19 15:54
  • ClassLoader类加载机制的核心引擎
  • C/C++复习--C语言中的函数详细
  • 强化学习系列:深度强化学习和DQN
  • 短剧平台流量突围!端原生片源授权成破局关键
  • 暗物质卯引力挂载技术
  • 【Bluedroid】蓝牙 HID 设备服务注册流程源码解析:从初始化到 SDP 记录构建