十五、Linux线程(二)

4.线程的分离属性

通过属性设置线程的分离

1.线程属性类型: pthread_attr_t attr;

2.线程属性操作函数:

        (1)对线程属性变量的初始化

                int pthread_attr_init(pthread_attr_t* attr);

        (2)设置线程分离属性

                int pthread_attr_setdetachstate(

                        pthread_attr_t* attr;

                        int detachstate;

                 );

参数:

        attr : 线程属性

        detachstate:

                PTHREAD_CREATE_DETACHED(分离)

                PTHREAD_CREATE_JOINABLE(非分离)

        (3)释放线程资源函数

                int pthread_attr_destroy(pthread_attr_t* attr);

5.线程同步

demo:

两个线程强占交替进行

数据混乱:

1.操作了共享资源

2.CPU调度问题

解决:

        线程同步:什么是同步?,协同步调,按照先后顺序操作执行

线程同步的思想:

6.互斥锁(互斥量)

特点:多个线程访问共享数据的时候是串行的

缺点:效率低

1.互斥锁使用的步骤

创建互斥锁: pthread_mutex_t mutex;

初始化:pthread_mutex_init(&mutex,NULL); ——mutex = 1

找到线程共同操作的共享数据:

        操作共享资源之前加锁:

        pthread_mutex_lock(&mutex); //阻塞 ——mutex = 0

        pthread_mutex_trylock(&mutex); // 如果锁上锁直接返回,不阻塞

        共享数据操作//临界区 ,越小越好

        解锁:pthread_mutex_unlock(&mutex); // ——mutex = 1

                阻塞在锁上的线程会被唤醒

销毁:pthread_mutex_destroy(&mutex)

2.互斥锁相关函数

初始化互斥锁:

pthread_mutex_init(

pthread_mutex_t* restrict mutex,

const pthread_mutexattr_t* restrict attr,

);

加锁:

pthread_mutex_lock(pthread_mutex* mutex)

mutex:

        没被锁上:当前线程会将这把锁锁上

        被锁上了:当前线程阻塞,锁被打开之后,线程解除阻塞

尝试加锁,失败返回,不阻塞:

pthread_mutex_trylock(pthread_mutex_t* mutex);

        没有锁上:当前线程会被这把锁加锁

        被锁上了:不会阻塞,返回

        返回0:加锁 成功   没锁上:返回错误号

if( pthread_mutex_trylock(& mutex)==0)

{

        //尝试加锁,并且成功了

        //访问共享资源

}

else

{

        //错误处理

        //或者等待,再次尝试加锁

}

解锁:

pthread_mutex_unlock(pthread_mutex_t* mutex)

销毁互斥锁:

pthread_mutex_destroy(pthread_mutex_t* mutex );

如果我们想要使用互斥锁同步线程所以线程都需要加锁

7.原子操作

CPU处理一个指令,进程/线程在处理完这个指令之前是不会失去CPU的

所谓原子操作,也就是一个独立而不可分割的操作,就像原子被认为是不可分割颗粒一样

更广泛的意义下原子操作是指一系列必须整体完成的操作步骤,如果任何一步操作没有完成,那么所有完成的步骤都必须回滚,这样就可以保证要么所有操作步骤都未完成,要么所有操作步骤都被完成

//示例代码1

void* procucer(void * arg)

{

        while(1)

        {

                //创建一个链表的节点

                Node * newNode = (Node*)malloc(sizeof(Node));

                //init

                newNode‐>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));

                //init

                newNode‐>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;

}

8.死锁

造成死锁的原因:

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

9.读写锁

1.读写锁是几把锁?

一把锁

pthread_rwlock_t lock;

2.读写锁的类型

读锁-对内存做读操作

写锁-对内存做写操作

3.读写锁的特性

线程A锁成功,又来了三个线程,做操作,可以加锁成功

        读共享——并行处理

线程A锁成功,又来了三个线程,做操作,三个线程阻塞

        写独占——串行处理

线程A锁成功,又来了三个线程,做操作,三个线程阻塞

        写独占——写完再读

线程A锁成功,又来了三个线程,做操作,三个线程阻塞

        读独占——读完再写

线程A加读锁成功,又来了B线程加写锁阻塞,又来了C线程加读锁阻塞

        读写不可以同时进行

        写的优先级高

4.读写锁场景练习

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

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

3、线程A持有读锁,线程B请求读锁 :线程B加锁

4、线程A持有读锁,线程B请求写锁,线程C请求读锁 :

        1.线程A持有读锁,线程B阻塞,线程C阻塞

        2.线程A读完之后,线程B加锁,线程C阻塞

        3.线程B写完之后,线程C加锁

5、线程A持有写锁,线程B请求读锁,线程C请求写锁:

        1.线程A持有写锁,线程B阻塞,线程C阻塞

        2.线程A写完之后,线程C加锁, 线程B阻塞

        3.线程C写完之后,线程B加锁

5.读写锁的适用场景

互斥锁:

        读写串行

读写锁:

        读:并行

        写:串行

6.主要操作函数

初始化读写锁:

        pthread_rwlock_init(pthread_rwlock_t* restrict rwlock,

        const pthread_rwlockattr_t* restrict attr );

加读锁:

        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);

                加锁成功:返回0

                失败:返回错误号

解锁:

        pthread_rwlock_unlock(pthread_rwlock_t* rwlock);

销毁读写锁:

        pthread_rwlock_destroy(pthread_rwlock_t* rwlock);

7.练习

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

先不加锁:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>int num = 0;void* write_fun(void* arg)
{while(1){num++;printf("write : %ld,%d\n",pthread_self(),num);usleep(500);}
}
void* read_fun(void* arg)
{while(1){printf("read : %ld,%d\n",pthread_self(),num);usleep(500);}
}int main()
{pthread_t p[8];for(int i = 0;i < 3;i++){pthread_create(&p[i],NULL,write_fun,NULL);}for(int i = 3;i < 8;i++){pthread_create(&p[i],NULL,read_fun,NULL);}for(int i = 0;i < 8;i++){pthread_join(p[i],NULL);}return 0;
}

在读的时候会发生混乱

加锁之后:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>int num = 0;
//create rwlock
pthread_rwlock_t lock;void* write_fun(void* arg)
{while(1){//lockpthread_rwlock_wrlock(&lock);num++;printf("write : %ld,%d\n",pthread_self(),num);//unlockpthread_rwlock_unlock(&lock);usleep(500);}
}
void* read_fun(void* arg)
{while(1){//lockpthread_rwlock_rdlock(&lock);printf("read : %ld,%d\n",pthread_self(),num);//unlockpthread_rwlock_unlock(&lock);usleep(500);}
}int main()
{//init rwlockpthread_rwlock_init(&lock,NULL);pthread_t p[8];for(int i = 0;i < 3;i++){pthread_create(&p[i],NULL,write_fun,NULL);}for(int i = 3;i < 8;i++){pthread_create(&p[i],NULL,read_fun,NULL);}for(int i = 0;i < 8;i++){pthread_join(p[i],NULL);}//destroy rwlockpthread_rwlock_destroy(&lock);return 0;
}

这次在读的时候不混乱了

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

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

相关文章

Unity学习笔记(1):素材导入

文章目录 前言学习目标开发环境资源文件下载Unity窗口设置修改导入像素素材设置可以直接拖动导入设置像素图片格式导入多合一素材设置切割 总结 前言 最近由于工作的事情&#xff0c;很糟心。最近非常的迷茫。 学习目标 根据我的加的几个QQ群了解到&#xff0c;国内游戏行业…

简历模板(艺术风)

每份简历模板都有四页 36款艺术风简历模板 一、水墨古风 二、唯美淡雅 三、时尚个性 四、艺术气质

数字乡村建设方案-5

1. 政策背景与乡村振兴战略 中国政府提出的乡村振兴战略&#xff0c;旨在全面建设小康社会和社会主义现代化国家&#xff0c;其中数字乡村建设是实现乡村全面振兴的关键途径。国家和江苏省相继出台政策&#xff0c;推动信息技术与农业生产生活的深度融合&#xff0c;加快农业农…

「C/C++」C++ STL容器库 之 std::map 键值容器类

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

2024 第五次周赛

A: 直接遍历即可 #include<bits/stdc.h> using namespace std;typedef long long ll; typedef pair<ll, ll>PII; const int N 2e6 10; const int MOD 998244353; const int INF 0X3F3F3F3F;int n, m; int main() {cin >> n;int cnt 0;for(int i 0; i …

Start SSM from stratch !!!

Start SSM from stratch !!! 数据库两个数据库可以共存吗&#xff1f;常见的关系数据库常见的非关系数据库数据库可视化管理工具 java版本reviewee and se?jdk1.7 or jdk7? mysql安装版本对应关系下载[MySQL](https://downloads.mysql.com/archives/installer/)下载[Connecto…

[C++11] 类中新特性的添加

默认的移动构造和移动赋值 在 C11 之前&#xff0c;编译器会为每个类自动生成默认的构造函数、析构函数、拷贝构造函数、拷贝赋值运算符等函数&#xff0c;以实现对象的创建、销毁和拷贝操作。但拷贝操作会复制整个对象的数据&#xff0c;效率低&#xff0c;尤其是在处理大对象…

AI 写作(六):核心技术与多元应用(6/10)

一、AI 写作的核心技术概述 AI 写作在当今数字化时代正发挥着越来越重要的作用。它不仅极大地提高了写作效率&#xff0c;还为不同领域带来了创新的可能性。 AI 写作的核心技术主要包括基于模板的文本生成和基于深度学习的文本生成。基于模板的文本生成通常依赖预先设定的模板…

用 Python 从零开始创建神经网络(三):添加层级(Adding Layers)

添加层级&#xff08;Adding Layers&#xff09; 引言1. Training Data2. Dense Layer Class 引言 我们构建的神经网络变得越来越受人尊敬&#xff0c;但目前我们只有一层。当神经网络具有两层或更多隐藏层时&#xff0c;它们变成了“深度”网络。目前我们只有一层&#xff0c…

ClickHouse 24.10 版本发布说明

本文字数&#xff1a;13817&#xff1b;估计阅读时间&#xff1a;35 分钟 作者&#xff1a;ClickHouse Team 本文在公众号【ClickHouseInc】首发 又到了新版本发布的时间&#xff01; 发布概要 本次ClickHouse 24.10 版本包含了25个新功能&#x1f381;、15项性能优化&#x1f…

AI4SCIENSE(鄂维南院士:再谈AI for Science)

鄂维南院士&#xff1a;再谈AI for Science_哔哩哔哩_bilibili 以往处理高维问题 量子力学&#xff1a;单变量乘积 统计学&#xff1a;旋转 AI4S 处理数据 蛋白质折叠&#xff1f; 不是纯粹的数据驱动 物理学等学科基本原理 例&#xff1a;分子动力学 数据模型 流程图 这…

华为云全新上线Serverless应用中心,支持一键构建文生图应用

近日&#xff0c;华为云全新上线Serverless应用中心&#xff0c;提供大量应用模板&#xff0c;帮助用户实现一键部署函数和周边依赖资源&#xff0c;节省部署时间&#xff0c;快速上手将应用部署到华为云函数工作流FunctionGraph&#xff0c;并一键开通周边依赖资源。 体验入口…

F5-TTS 整合包详细部署文档1110更新

F5-TTS 整合包详细部署文档&#xff1a;1110更新 F5-TTS 整合包详细部署教程1110更新 更新内容 本次更新加入了通义千问对话模型&#xff0c;以增强F5-TTS的功能和性能。 下载相关资源 F5-TTS文本转语音 链接&#xff1a;F5-TTS资源下载 文件列表 文件名大小说明01-主程序…

【bayes-Transformer-GRU多维时序预测】多变量输入模型。matlab代码,2023b及其以上

% 1. 数据准备 X_train 训练数据输入; Y_train 训练数据输出; X_test 测试数据输入; % 2. 模型构建 inputSize size(X_train, 2); numHiddenUnits 100; numResponses 1; layers [ … sequenceInputLayer(inputSize) biLSTMLayer(numHiddenUnits, ‘OutputMode’, ‘se…

AUTOSAR CP TCP/IP堆栈规范导读

一、规范的主要内容 该规范是AUTOSAR中关于TCP/IP堆栈的规范&#xff0c;主要内容包括以下几个方面&#xff1a; 总体介绍 功能概述&#xff1a;提供了发送和接收互联网协议数据的功能&#xff0c;位于Socket Adaptor和以太网接口模块之间。文档信息&#xff1a;包含文档标题…

redis安装

Redis的安装配置 安装Redis 安装gcc依赖 Redis是使用C语言编写的&#xff0c;Linux上并没有C语言的编译器&#xff0c;需要手动安装 yum install -y gcc tcl上传安装包并解压 将压缩包放在任意目录解压 tar -xzf redis-6.2.6.tar.gz安装 1.进入redis目录 cd redis-6.2.62.运行…

Linux系统程序设计--3. 文件操作

文件属性 存放文件属性的结构体 文件属性操操作函数 文件类型(7种) - 普通文件d目录p 管道文件l 符号链接(软链接) 判断文件类型的小程序 #include<sys/types.h> #include<sys/stat.h> #include<string.h> #include<stdio.h> #include<memory.h&…

单词反转和数组去重,附经典面试题一份

博彦科技笔试&#xff1a; 给定字符&#xff0c;拼接成单词进行反转单词&#xff1b; package org.example;public class Main {public static void main(String[] args) {char[] input {h, e, l, l, o, , w, o, r, l, d, , J, a, v, a};String inputToString new String(…

HTB:Precious[WriteUP]

目录 连接至HTB服务器并启动靶机 使用nmap对靶机TCP端口进行开放扫描 使用curl访问靶机80端口 使用ffuf爆破一下子域 使用浏览器访问该域名 使用curl访问该域名响应头 使用exiftool工具查看该pdf信息 横向移动 USER_FLAG&#xff1a;adf5793a876a190f0c08b3b6247cec32…

【2024.11.10实测有效:Win11右键默认显示更多设置教程】

winX 选择管理员 reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve# 再 taskkill /f /im explorer.exe & start explorer.exe! none taskkill /f /im explorer.exe; start explorer.exe