线程互斥,线程安全和线程同步

news2024/12/23 18:50:30

多线程的基本代码编写步骤

1.创建线程pthread_create()
2.终止线程的三种方法。线程取消pthread_cancel(一般在主线程取消), 线程终止pthread_exit(在其他线程执行), 或者使用线程返回return
3.线程等待pthread_join

需要等待的原因是
1.已经退出的线程,其空间没有被释放,仍然在进程的地址空间内。
2.创建新的线程不会复用刚才退出线程的地址空间。

创建线程

功能:创建一个新的线程
原型

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *
(*start_routine)(void*), void *arg);
参数
thread:返回线程ID
attr:设置线程的属性,attr为NULL表示使用默认属性
start_routine:是个函数地址,线程启动后要执行的函数
arg:传给线程启动函数的参数

返回值:成功返回0;失败返回错误码

线程终止

phread_exit函数
功能:线程终止
原型

void pthread_exit(void *value_ptr);
参数
value_ptr:value_ptr不要指向一个局部变量。

线程取消

pthread_cancel函数
功能:取消一个执行中的线程
原型

int pthread_cancel(pthread_t thread);
参数
thread:线程ID
返回值:成功返回0;失败返回错误码

线程等待

功能:等待线程结束
原型

int pthread_join(pthread_t thread, void **value_ptr);
参数
thread:线程ID
value_ptr:它指向一个指针,后者指向线程的返回值
返回值:成功返回0;失败返回错误码

调用该函数的线程将挂起等待,直到id为thread的线程终止。thread线程以不同的方法终止,通过pthread_join得到的
终止状态是不同的,总结如下:

  1. 如果thread线程通过return返回,value_ ptr所指向的单元里存放的是thread线程函数的返回值。
  2. 如果thread线程被别的线程调用pthread_ cancel异常终掉,value_ ptr所指向的单元里存放的是常数
    PTHREAD_ CANCELED。
  3. 如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元存放的是传给pthread_exit的参
    数。
  4. 如果对thread线程的终止状态不感兴趣,可以传NULL给value_ ptr参数。

三种情况代码示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
void *thread1(void *arg)
{
    printf("thread 1 returning ... \n");
    int *p = (int *)malloc(sizeof(int));
    *p = 1;
    return (void *)p;
}
void *thread2(void *arg)
{
    printf("thread 2 exiting ...\n");
    int *p = (int *)malloc(sizeof(int));
    *p = 2;
    pthread_exit((void *)p);
}
void *thread3(void *arg)
{
    while (1)
    { //
        printf("thread 3 is running ...\n");
        sleep(1);
    }
    return NULL;
}
int main(void)
{
    pthread_t tid;
    void *ret;
    // thread 1 return
    pthread_create(&tid, NULL, thread1, NULL);
    pthread_join(tid, &ret);
    printf("thread return, thread id %X, return code:%d\n", tid, *(int *)ret);
    free(ret);
    // thread 2 exit
    pthread_create(&tid, NULL, thread2, NULL);
    pthread_join(tid, &ret);
    printf("thread return, thread id %X, return code:%d\n", tid, *(int *)ret);
    free(ret);
    // thread 3 cancel by other
    pthread_create(&tid, NULL, thread3, NULL);
    sleep(3);
    pthread_cancel(tid);
    pthread_join(tid, &ret);
    if (ret == PTHREAD_CANCELED)
        printf("thread return, thread id %X, return code:PTHREAD_CANCELED\n", tid);
    else
        printf("thread return, thread id %X, return code:NULL\n", tid);
}

互斥概念

互斥:多个执行流在同一时刻,只有一个执行流进入临界区。

对于Linux的互斥锁,加锁和解锁 的操作都是原子性的。
当线程A拿到锁后,其他线程虽然也可以切换到改代码块,但是锁是被 A拿走的,其他线程无法申请到锁,所以就无法进入临界区。这就是互斥

互斥锁的加锁和解锁原子性是如何实现的

以下是锁的其中一个实现方式。

交换的汇编xchgb是原子性的。

在这里插入图片描述
本质:将cpu寄存器中的值交换到线程的上下文中,变成了线程私有的。从而实现加锁解锁为原子性。

线程安全

重入:同一个函数被不同执行流执行调用,当前执行流还没执行完,其他执行流就进入了。这叫做重入。
可重入函数:在重入的基础上,运行结果不会出现任何问题,则该函数就是可重入函数。

函数是可重入的,那么他就一定是线程安全的。

线程不安全就是并发的时候出现问题,不管他是否是可重入或不可重入。

死锁

自己和对方互相申请对方的握着不放的资源,这就叫做死锁。

特殊情况:一把锁也能产生死锁。比如:一把锁连续申请两次加锁,这就会产生死锁。

产生死锁的四个必要条件:
互斥条件:一个资源每次只能被一个执行流使用
请求和保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不放
不剥夺条件:不能强行剥夺资源,比如申请了锁,还没使用完,不能强行剥夺锁。
循环等待条件:若干执行流形成头尾相连循环等待资源的关系

线程同步

线程互斥合理吗?

互斥可能导致饥饿问题:一个执行流,长时间得不到某种资源。

同步:在保证数据安全的前提下,让线程按照特定的顺序访问临界资源,从而有效避免饥饿问题。
静态条件:因为时序问题,而导致程序异常,我们称之为竞态条件。

volatile

使用 volatile 关键字并不意味着就不需要加锁了。volatile 和锁机制解决的是不同层面的并发问题。

volatile 主要解决的是:

变量的可见性问题
    确保一个线程对变量的修改对其他线程可见。

禁止指令重排序
    防止编译器和 CPU 对指令进行重排优化,保证代码执行的顺序性。

但 volatile 并不能解决:

原子性问题
    对共享变量的复合操作(如 i++)仍然可能出现数据竞争。

线程安全问题
    复杂的并发操作,如链表的插入和删除,仍然需要加锁来保证线程安全。

因此,在多线程编程中,volatile 和锁机制是相辅相成的:

volatile 用于解决可见性和有序性问题。
锁机制用于解决原子性和线程安全问题。

简单的共享变量可以使用 volatile 关键字来保证可见性和有序性,但对于复杂的并发操作,仍然需要使用锁来确保线程安全。

条件变量

同步是使用条件变量来实现的。
互斥是使用互斥锁来实现的。

条件变量初始化

int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict
attr);
参数:
cond:要初始化的条件变量
attr:NULL

销毁

int pthread_cond_destroy(pthread_cond_t *cond)

等待条件满足

int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
参数:
cond:要在这个条件变量上等待
mutex:互斥量,后面详细解释

唤醒等待

int pthread_cond_broadcast(pthread_cond_t *cond);//唤醒全部
int pthread_cond_signal(pthread_cond_t *cond);

生产者消费者模型(同步和互斥的最经典场景 ) 重新认识条件变量

生产者消费者模式就是通过一个缓冲区来解决生产者和消费者的强耦合问题,提高了效率。生产者和消费者不直接通讯,而是通过缓冲区通信。

利用一个缓冲区(内存中特定的一种数据结构), 生产者(线程),消费者(线程)。

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

解决的问题

利用一个缓冲区(内存中特定的一种数据结构)
1.解耦合
2.提高效率

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1605906.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java程序生成可执行的exe文件 详细图文教程

1.Java编辑器&#xff0c;如&#xff1a;idea、eclipse等&#xff0c;下载地址&#xff1a;IntelliJ IDEA: The Capable & Ergonomic Java IDE by JetBrainshttps://www.jetbrains.com/idea/2.exe4j&#xff0c;下载地址&#xff1a;ej-technologies - Java APM, Java Prof…

spring 集成 mybatis

spring 集成 mybatis 1、spring对junit的支持1.1、对junit4的支持1.2 对junit5的支持 2、Spring6集成MyBatis3.52.1 实现步骤2.2 实现 1、spring对junit的支持 1.1、对junit4的支持 依赖 <?xml version"1.0" encoding"UTF-8"?> <project xml…

基于XML配置bean(一)

文章目录 1.获取bean的两种方式1.通过id获取bean&#xff08;前面用过&#xff09;2.通过类型获取bean&#xff08;单例时使用&#xff09;1.案例2.代码1.beans.xml2.SpringBeanTest.java3.结果 3.注意事项 2.三种基本依赖注入方式1.通过属性配置bean&#xff08;前面用过&…

图与图搜索算法

图搜索算法是一个非常重要的概念&#xff0c;它是计算机科学中图论和算法设计的基础部分。在开始讨论图搜索算法之前&#xff0c;我们需要先理解什么是图以及图的基本结构。 什么是图&#xff1f; 图&#xff08;Graph&#xff09;是一种非线性数据结构&#xff0c;它由一组点…

通过vue完成表格数据的渲染展示和vue的生命周期及小结

案例 通过vue完成表格数据的渲染展示 把视图区展示的数据 死数据替换掉 从vue的数据模型中读取 展示在视图区 vue中的数据 模型是js中的自定义类型 形成的数组 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">&l…

Mathorcup 甲骨文识别

本资源主要包含第2-4问&#xff0c;第一问直接使用传统图像处理即可&#xff0c;需要有很多步骤&#xff0c;这一步大家自己写就行。 2 第2问&#xff0c;甲骨文识别 2.1 先处理源文件 原文件有jpg和json文件&#xff0c;都在一个文件夹下&#xff0c;需要对json文件进行处理…

Python路面车道线识别偏离预警

程序示例精选 Python路面车道线识别偏离预警 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《Python路面车道线识别偏离预警》编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易…

牛客Linux高并发服务器开发学习第三天

静态库的使用(libxxx.a) 将lession04的文件复制到lession05中 lib里面一般放库文件 src里面放源文件。 将.c文件转换成可执行程序 gcc main.c -o app main.c当前目录下没有head.h gcc main.c -o app -I ./include 利用-I 和head所在的文件夹&#xff0c;找到head。 main.c…

针对springcloud gateway 跨域问题解决方案

springcloud gateway版本 <spring-boot.version>2.3.3.RELEASE</spring-boot.version> <spring-cloud.version>Hoxton.SR8</spring-cloud.version>跨域问题说明 application:1 Access to XMLHttpRequest at https://xxxxxxxxxx from origin http://l…

<计算机网络自顶向下> 可靠数据传输的原理(未完成)

可靠数据传输&#xff08;rdt&#xff1a;Reliable Data Transfer&#xff09;的原理 rdt在应用层&#xff0c;传输层和数据链路层都很重要是网络TOP10问题之一信道的不可靠特点决定了可靠数据传输rdt的复杂性rdt_send: 被上层&#xff08;如应用层&#xff09;调用&#xff0…

IP-guard WebServer 权限绕过漏洞复现(QVD-2024-14103)

0x01 免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删…

Simlab python二次开发1-将所有缸套内表面半径加大1mm

Simlab python二次开发1-将所有缸套内表面半径加大1mm 1、打开模型文件2、getBodiesWithSubString&#xff08;&#xff09;从名字得到Bodies3、建Body类Group3.1、定义放入Group中的Bodies3.2、建Group 4、将缸套内表面建组&#xff0c;并扩半径1mm4.1、simlab.getBodiesFromG…

[生活][杂项] 上班党的注意事项

前言 目前是上班已经接近两年了&#xff0c;目前的状态是&#xff0c;一个人租了一个单间在上班。对于这种情况有以下几点需要注意。 钥匙问题&#xff0c;一定不要陷入钥匙丢失的情况&#xff01;一定不要陷入钥匙丢失的情况&#xff01;一定不要陷入钥匙丢失的情况&#xff…

OpenHarmony多媒体-video_trimmer

简介 videotrimmer是在OpenHarmony环境下&#xff0c;提供视频剪辑能力的三方库。 效果展示&#xff1a; 安装教程 ohpm install ohos/videotrimmerOpenHarmony ohpm环境配置等更多内容&#xff0c;请参考 如何安装OpenHarmony ohpm包 。 使用说明 目前支持MP4格式。 视频…

Flattened Butterfly 扁平蝶形拓扑

Flattened Butterfly 扁平蝶形拓扑 1. 传统蝶形网络 Butterfly Topology2. 扁平蝶形拓扑 Flattened Butterfly3.On-Chip Flattened Butterfly 扁平蝶形拓扑应用于片上网络 Flattened Butterfly 扁平蝶形拓扑 扁平蝶形拓扑是一种经济高效的拓扑&#xff0c;适用于高基数路由器…

Golang入门基础

文章目录 Golang的背景知识Golang的发展历程Golang的特点Golang的应用领域 开发环境搭建下载并安装SDK包设置环境变量Go项目目录结构 注释变量标识符命名输入和输出运算符算术运算符关系运算符逻辑运算符赋值运算符位运算符其他运算符 Golang的背景知识 Golang的发展历程 Gola…

2024年华中杯数学建模竞赛ABC题思路分析

简单分析一下各个题目可能需要用到的方法和模型&#xff0c;完整代码和成品论文见文末 A题 太阳能路灯光伏板的朝向设计问题: 1. 球面几何、天文学相关知识,如赤纬角、太阳高度角、时角等概念和公式 2. 太阳辐射模型,根据太阳能辐射强度、大气衰减系数等计算地表太阳辐射强度…

2.核心概念与安装配置

核心概念与安装配置 文章目录 核心概念与安装配置1、核心概念Docker整体架构及底层通信原理 2、安装DockerCentos安装Docker引擎阿里云镜像加速Docker run的过程 3、Docker相关命令 1、核心概念 镜像&#xff08;image&#xff09; Docker 镜像&#xff08;Image&#xff09;就…

【三维Dvhop定位】基于麻雀搜索算法的多通信半径和跳距加权的三维Dvhop定位算法【Matlab代码#81】

文章目录 【可更换其他算法&#xff0c;获取资源请见文章第6节&#xff1a;资源获取】1. Dvhop定位算法2. 麻雀搜索算法3. 多通信半径和跳距加权策略3.1 多通信半径策略3.2 跳距加权策略 4. 部分代码展示5. 仿真结果展示6. 资源获取 【可更换其他算法&#xff0c;获取资源请见文…

Istio介绍

1.什么是Istio Istio是一个开源的服务网格&#xff08;Service Mesh&#xff09;框架&#xff0c;它提供了一种简单的方式来为部署在Kubernetes等容器编排平台上的微服务应用添加网络功能。Istio的核心功能包括&#xff1a; 服务治理&#xff1a;Istio能够帮助管理服务之间的…