线程封装,互斥

文章目录

  • 线程封装
  • 线程互斥
  • 加锁、解锁
    • 认识接口
    • 解决问题
    • 理解锁

线程封装

C/C++代码混编引起的问题
在这里插入图片描述

此处pthread_create函数要求传入参数为void * func(void * )类型,按理来说ThreadRoutine满足,但是
这是在内类完成封装,所以ThreadRoutine函数实际是两个参数,第一个参数Thread* this不显示

解决方法:
第一种:写在类外,不推荐,封装性质降低
第二种:
在这里插入图片描述

首先将方法写为static方法,然后为了调用_func函数,将原本传入的参数由名称指针改为this指针
然后对this指针进行修改,用void*接受,利用static_cast<>可以更好的适应(自动变为我们需要的指针类型)
这边的t就是this,但是不能写为this,与内置冲突

多线程的创建和管理

在这里插入图片描述c++11语法的使用
在这里插入图片描述

• push_back:需要一个已经构造好的对象,并将其复制或移动到容器中。
• emplace_back:直接在容器末尾构造对象,避免了不必要的复制或移动操作

利用模版参数进行传递修改代码,保障自己需要的内容是什么
在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这里插入图片描述这样就完成了一个带自定义参数的线程任务的创建执行
在这里插入图片描述

完整代码
Thread.hpp

#pragma once
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <string>
#include <functional>using namespace std;
template<class T>
using func_t = function<void(T)>;
template<class T>
class Thread
{
public:Thread(const string& name, func_t<T> func, T data):_tid(0), _name(name), _isrunning(false), _func(func), _data(data){}static void* ThreadRoutine(void* args){Thread* t = static_cast<Thread*>(args);t->_func(t->_data);exit(0);}bool Start(){int n = pthread_create(&_tid, nullptr, ThreadRoutine, this);if(n == 0){_isrunning = true;return true;}else {return false;}}bool join(){if(!_isrunning){return true;}int n = pthread_join(_tid, nullptr);if(n == 0){_isrunning = false;return true;}else {return false;}}~Thread(){cout << "~Thread()" << endl;}bool IsRunning(){return _isrunning;}
private:pthread_t _tid;string  _name;bool _isrunning;func_t<T> _func;T _data;
};

main.cc

#include <iostream>
#include "Thread.hpp"
#include <vector>void Print(int cnt)
{while(cnt--){cout << "hello world" << endl;sleep(1);}
}
string GetThreadName()
{static int num = 0;return static_cast<string>("Thread-") + to_string(++num);
}int main()
{Thread<int> t(GetThreadName(), Print, 10);t.Start();t.join();// int num = 5; // vector<Thread> threads;// for(int i = 0; i < num; ++i)// {//     threads.emplace_back(Print, GetThreadName());// }// for(int i = 0; i < num; ++i)// {//     cout << "Is thread is running? " << threads[i].IsRunning() << endl;// }// for(int i = 0; i < num; ++i)// {//     threads[i].Start();// }// for(int i = 0; i < num; ++i)// {//     cout << "Is thread is running? " << threads[i].IsRunning() << endl;// }// for(int i = 0; i < num; ++i)// {//     threads[i].join();// }return 0;
}

makefile文件

test_Thread:main.ccg++ -o $@ $^ -std=c++11
.PHONY:clean
clean:rm -f test_Thread

线程互斥

单线程抢票逻辑:
在这里插入图片描述

多线程模拟实现:
在这里插入图片描述
在这里插入图片描述

多线程会出现线程同步访问一个数据的情况,这种情况是不允许的,也不希望出现这种情况
任何时刻,只允许一个线程正在访问共享资源,这样的资源叫做临界资源

在这里插入图片描述互斥:任何时候只允许一个执行流进入临界区
访问临界资源,起到保护作用
原子性:不会被任何调度机制打断,该操作只有两态,要么完成,要么未完成
例如:

int cnt = 10;
cnt++;

这串代码会在汇编情况下变为三条语句
在这里插入图片描述在这里插入图片描述
他并不是原子的,多线程下,任何一句都可能被打断
计算机内硬件(寄存器)只有一套,但是数据是各自的私有的

多线程并发访问的时间片截止到时数据不一致问题:

在这里插入图片描述对于线程 1:
第一步 从内存将数值10写入寄存器
第二步 加加操作
在这时,他的时间片到了,那么这个时候就会进行上下文的保存

然后回进行线程2的运行:
第一步,第二步,…循环进行到cnt的值假设到了100
这时轮到线程1,线程1会进行上下文内的替换
那么这个100会被替换为11,这样这个操作就付之东流了~~

这个现象说明了,多线程并发访问cnt,不是原子的
会有数据不一致的并发访问问题

那么ticket变为负数也是这样的,这完全就是混乱的,判断也是计算
CPU有四种功能,

算:算术运算
逻:逻辑运算
中:处理内外中断
控:控制单元(时钟单元,取指令,用指令的执行)

比如上述减到负数,是因为,刚开始是并行执行逻辑判断假设ticket == 1,但是到了–操作时变成了穿行执行,假设是同时是4个执行流进入,执行流同时进行减减操作,就会减为负数的情况
这是小概率的事件,但是本质就是如此

数据在内存中是被线程共享的.
数据被读到寄存器中,本质就变成了线程的上下文,属于线程的私有数据

此时就需要加锁进行保护

加锁、解锁

认识接口

linux中进行加锁:使用pthread_mutex_init (mutex:互斥量)
在这里插入图片描述

要使用全局定义一个锁,就需要进行初始化
类型为pthread_mutex_t
初始化为PTHREAD_MUTEX_INITIALIZER
也不需要对他进行销毁,全局变量会自动进行销毁

要定义为一个局部的锁,就需要使用函数
在这里插入图片描述

局部的锁要进行销毁操作

解决问题

创建之后的加锁解锁函数
在这里插入图片描述

理解锁

加锁(以牺牲效率为代价进行解决问题):

1.给尽可能少的代码块进行加锁
2.一般加锁,都是给临界区进行加锁
执行加锁代码:

在这里插入图片描述
在这里插入图片描述
可以看到虽然正常执行,但是代码的执行速度显著下降
去掉加锁后,速度又快了不少

1.锁被创建之后,虽然它是全局变量,但是它是安全的,本身是原子性的.
2.程序员自己必须保障给临界区加锁
3.根据锁的定义,加锁只允许一个执行流进入这个临界区,所以加锁操作也只存在在一个执行流中,这时多个线程申请锁失败,失败的线程在mutex上进行阻塞,即本质进行等待
所以上述就有了,

在这里插入图片描述

pthread_mutex_trylock()的使用,成功往下走,不成功返回一个值进行程序员自行发挥
4.加锁之后,线程也可能会切换,但是其他线程处于等待状态,所以相当于当前线程抱着锁走,等他解锁才会被完全切换到其他线程(这把锁被使用期间,不能别其他任何线程使用,这也很好的保证了他的原子性)

喜欢不妨来个三连~~~

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

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

相关文章

【建设方案】大数据湖一体化建设方案(ppt原件)

1、背景&#xff1a;大数据湖的发展背景与建设理念 2、体系&#xff1a;大数据湖体系规划与建设思路 3、生态圈&#xff1a;探索新兴业务入湖建设模式 4、共享&#xff1a;大数据湖统一访问共享规划 5、运营&#xff1a;大数据湖一体化运营管理建设 &#xff08;本方案及更多方…

Kafka~基础原理与架构了解

Kafka是什么 Kafka我们了解一直认为是一个消息队列&#xff0c;但是其设计初&#xff0c;是一个&#xff1a;分布式流式处理平台。流平台具有三个关键功能&#xff1a; 消息队列&#xff1a;发布和订阅消息流&#xff0c;这个功能类似于消息队列&#xff0c;这也是 Kafka 也被…

Comfyui-ChatTTS-OpenVoice 为ComfyUI添加语音合成、语音克隆功能

‍‍ 生成多人播客&#xff1a; Comfyui-ChatTTS是一个开源的GitHub项目&#xff0c;致力于为ComfyUI添加语音合成功能。该项目提供了一系列功能强大的节点和模型&#xff0c;支持用户创建和复用音色&#xff0c;支持多人对话模式的生成&#xff0c;并提供了导出音频字幕文件的…

“Jedis与Redis整合指南:实现高效的Java应用与Redis交互“

目录 #. 概念 1. 导入jedis依赖 2. 写一个类&#xff08;ping通redis&#xff09; 3. String字符串使用 3.1 set&#xff0c;get方法使用&#xff08;设值&#xff0c;取值&#xff09; 3.2 mset&#xff0c;mget方法使用&#xff08;设置多个值&#xff0c;取多个值&…

怎么在vscode里运行一个cpp文件

文章目录 1.需要下载g编译器&#xff0c;或clang&#xff08;快&#xff0c;但是优化效果没有g好&#xff09;2.新建文件夹和cpp文件&#xff08;tasks.json&#xff09;3.怎么在vscode里调试(launch.json)4.怎么设置让中断输出的字符是中文&#xff01;5.飞机大战 1.需要下载g…

iis下asp.netcore后台定时任务会取消

问题 使用BackgroundService或者IHostedService做后台定时任务的时候部署到iis会出现不定时定时任务取消的问题&#xff0c;原因是iis会定时的关闭网站 解决 应用程序池修改为AlwaysRunning 修改web.config <?xml version"1.0" encoding"utf-8"?…

Android studio登录Google账号超时的解决方法

确保自己已经打开了代理&#xff08;科学上网&#xff09;在设置-外观与行为-系统设置-HTTP代理 中打开“自动检测代理设置”&#xff1a; 再次重新尝试登录Google账号&#xff0c;登陆成功&#xff01; 学术会议征稿 想要了解国内主办的覆盖学科最全最广的学术会议&#xff0c…

代码-功能-python-爬取博客网标题作者发布时间

环境&#xff1a; python 3.8 代码&#xff1a; # 爬取博客园内容 # https://www.cnblogs.com/import re from lxml import etree import requests import json import threading from queue import Queue import pymysql import timeclass HeiMa:def __init__(self):# 请…

k8s 部署 ruoyi 前后端分离项目

本文视频版 https://www.bilibili.com/video/BV17ugkePEeN 参考 https://blog.csdn.net/qq_50247813/article/details/136934090 https://gitee.com/nasaa/RuoYi-Vue-cloud https://www.itsgeekhead.com/tuts/kubernetes-129-ubuntu-22-04-3/ https://kubernetes.io/docs/se…

【漏洞复现】畅捷通T+ keyEdit.aspx SQL漏洞

0x01 产品简介 畅捷通 T 是一款灵动&#xff0c;智慧&#xff0c;时尚的基于互联网时代开发的管理软件&#xff0c;主要针对中小型工贸与商贸企业&#xff0c;尤其适合有异地多组织机构(多工厂&#xff0c;多仓库&#xff0c;多办事处&#xff0c;多经销商)的企业&#xff0c;…

用户态协议栈06-TCP三次握手

最近由于准备软件工程师职称考试&#xff0c;然后考完之后不小心生病了&#xff0c;都没写过DPDK的博客了。今天开始在上次架构优化的基础上增加TCP的协议栈流程。 什么是TCP 百度百科&#xff1a;TCP即传输控制协议&#xff08;Transmission Control Protocol&#xff09;是…

LabVIEW程序退出后线程仍在运行问题

LabVIEW程序退出后&#xff0c;线程仍在运行的问题可能源于资源管理不当、未正确终止循环、事件结构未处理、并发编程错误以及外部库调用未结束等方面。本文将从这些角度详细分析&#xff0c;探讨可能的原因和解决方案&#xff0c;并提供预防措施&#xff0c;帮助开发者避免类似…

将知乎专栏文章转换为 Markdown 文件保存到本地

一、参考内容 参考知乎文章代码 | 将知乎专栏文章转换为 Markdown 文件保存到本地&#xff0c;利用代码为GitHub&#xff1a;https://github.com/chenluda/zhihu-download。 二、步骤 1.首先安装包flask、flask-cors、markdownify 2. 运行app.py 3.在浏览器中打开链接&…

已解决javax.management.BadStringOperationException异常的正确解决方法,亲测有效!!!

已解决javax.management.BadStringOperationException异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 问题分析 出现问题的场景 报错原因 解决思路 解决方法 分析错误日志 检查字符串值合法性 确认字符串格式 优化代码逻辑 增加…

Trimesh介绍及基本使用

Trimesh介绍及基本使用 Trimesh是一个纯Python 工具库&#xff08;支持3.7版本以上&#xff09;&#xff0c;用于加载和使用三角形Mesh网格&#xff0c;支持多种常见的三维数据格式&#xff0c;如二进制/文本格式的STL、Wavefront OBJ、二进制/文本格式的PLY、GLTF/GLB 2.0、3…

Leetcode 2713. 矩阵中严格递增的单元格数(DFS DP)

Leetcode 2713. 矩阵中严格递增的单元格数 DFS 容易想到&#xff0c;枚举每个点作为起点&#xff0c;向同行同列的可跳跃点dfs&#xff0c;维护全局变量记录可达的最远距离 超时&#xff0c;通过样例193 / 566 class Solution {int res 0;public void dfs(int[][] mat, in…

EtherCAT笔记(三) —— 主站与从站的硬件组成

1. EtherCAT 主站的硬件组成 EtherCAT主站使用标准以太网控制器&#xff0c;也即EtherCAT主站可以使用以太网控制器的任何设备。当我们有一台带网口的笔记本、工控机&#xff0c;甚至是树莓派也可以作为EtherCAT主站。 EtherCAT协议是对Ethernet协议在实时控制等方面的优化&am…

android关于源码编译简单的apk处理

文章目录 简述文件的添加 简述 创建AOSP源码可编译一个简单apk的过程&#xff0c;代码子目录结构图如下所示 文件的添加 1.com.custom.test目录下创建TestActivity.java文件 用于简单的界面显示类 package com.custom.test;import android.app.Activity; import android.o…

高考填报志愿不容易,压线考生怎么救?

每年的高考季 就是高考生们水深火热的一大月份&#xff0c;很多考生都会纠结要报考哪些学校&#xff0c;哪些专业好&#xff0c;并非每个学生从小就有明确的目标&#xff0c;很多人到6月份才深思这个问题&#xff0c;此时难免手慌脚乱&#xff0c;更别说一些考生的分数处于一本…

创建第一个Springboot项目(环境准备、环境存在的问题、启动时存在的问题、启动的方式)

一、环境准备 专业版创建springboot&#xff0c;直接有一个选项可以选择 社区版&#xff0c;需要下载一个spring的插件 不要直接点 install 因为这个插件是付费的&#xff0c;直接点安装只有30天使用期限 在里面找免费版本的下载 然后安装 安装完成后&#xff0c;这个插件名会变…