提供免费服务器的网站/给你一个网站怎么优化

提供免费服务器的网站,给你一个网站怎么优化,电脑制作网站总么做,如何做百万格子网站在linux内核中并没有线程的概念,只有轻量级进程LWP的概念,linux下的线程都是是由LWP进行模拟实现的。因此linux操作系统中不会提供线程的相关接口,只会提供轻量级线程的接口(如vfork,clone等)。但是在我们的…

在linux内核中并没有线程的概念,只有轻量级进程LWP的概念,linux下的线程都是是由LWP进行模拟实现的。因此linux操作系统中不会提供线程的相关接口,只会提供轻量级线程的接口(如vfork,clone等)。但是在我们的学习过程中实际上学到的都是线程的概念,故而linux的设计者在用户和操作系统之间将轻量级进程的的系统调用进行了封装成库并提供给了用户,这样的线程我们称之为用户级线程库

接下来我们介绍一下linux系统中线程库的使用与封装。

一、线程库的使用

1.1 POSIX线程库

在linux中,与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以pthread_ 打头的。要想使用这些函数库,要通过引入头文件 <pthread.h>,而在链接这些线程函数库时要使用编译器命令的-lpthread选项。

1.2 线程库的接口

1.2.1 线程创建

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,失败返回错误码

示例:

#include<iostream>
#include<pthread.h>
#include<unistd.h>
using namespace std;void* run(void* arg)
{while(true){cout<<"new thread :"<<(char* )arg<<endl;sleep(1);}
}int main()
{pthread_t thread1;pthread_create(&thread1,nullptr,run,(void*)"new thread1");pthread_t thread2;pthread_create(&thread2,nullptr,run,(void*)"new thread2");while(true){cout<<"main thread"<<endl;sleep(1);}return 0;
}

注意:
• 新线程和主线程的运行顺序是不确定的。
• 多线程的调度时间是基于对进程的时间片进行瓜分。
• 多个线程向同一个文件(这里是显示器)进行写入时,在不加保护的情况下是会发生重入的,也就会产生数据不一致问题。
• 线程是共享进程地址空间的。
• 线程出现异常会导致当前进程的其他线程全部崩溃。

1.2.2 线程终止

和进程一样,线程创建之后也是要被等待和回收的!

如果需要只终止某个线程而不终止整个进程的话,有三种方法:
• 线程执行函数return。这种方法对主线程不适用,main函数return相当于调用exit。
• 线程可以调用pthread_exit终止自己。

void pthread_exit(void *value_ptr);
//功能:线程终⽌
//参数://value_ptr:线程退出时的返回值。

需要注意pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是用malloc分配的,不能在线程函数的栈上分配。因为当其它线程得到这个返回指针时线程函数已经退出了。

• 一个线程可以调用pthread_cancel终止同一进程中的另一个线程。

int pthread_cancel(pthread_t thread);
//功能:取消一个执⾏中的线程
//参数://thread:要取消的线程ID
//返回值:成功返回0,失败返回错误码

1.2.3 线程等待

为什么需要线程等待?
因为已经退出的线程其空间没有被释放,仍然在进程的地址空间内。而创建新的线程不会复用刚才退出线程的地址空间。

int pthread_join(pthread_t thread, void **value_ptr);
//功能:等待线程结束
//参数://thread:线程ID//value_ptr:用以保存线程的返回值的地址
//返回值:成功返回0;失败返回错误码

调用该函数的线程将挂起等待,直到id为thread的线程终止。

thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的:
• 如果thread线程通过return返回,那么value_ptr所指向的单元里存放的是thread线程函数的返回值。
• 如果thread线程被别的线程调用pthread_cancel异常终掉,value_ptr所指向的单元里存放的是常数PTHREAD_CANCELED((void*)-1)。
• 如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元存放的是传给pthread_exit的参数。
• 如果对thread线程的终止状态不感兴趣,则可以传NULL给value_ptr参数。

在这里插入图片描述
示例:

#include<iostream>
#include<pthread.h>
#include<unistd.h>
using namespace std;void* run1(void* arg)
{int count=5;while(count--){cout<<"new thread :"<<(char* )arg<<endl;sleep(1);}pthread_exit((void*)100);cout<<"退出成功!"<<endl;}void* run2(void* arg)
{while(true){cout<<"new thread :"<<(char* )arg<<endl;sleep(1);}
}
int main()
{//创建线程1,线程2pthread_t thread1;pthread_create(&thread1,nullptr,run1,(void*)"new thread1");pthread_t thread2;pthread_create(&thread2,nullptr,run2,(void*)"new thread2");sleep(3);//取消线程2pthread_cancel(thread2);cout<<"取消成功!"<<endl;//线程等待void *ret1,*ret2;pthread_join(thread1,&ret1);pthread_join(thread2,&ret2);cout<<"等待成功!"<<endl;cout<<"ret1 :"<<(long long)ret1<<";ret2 :"<<(long long)ret2<<endl;return 0;
}
caryon@VM-24-10-ubuntu:~/linux/thread$ ./thread 
new thread :new thread1
new thread :new thread2
new thread :new thread1
new thread :new thread2
new thread :new thread1
new thread :new thread2
取消成功!
new thread :new thread1
new thread :new thread1
等待成功!
ret1 :100;ret2 :-1

在多执行流的情况下,主执行流往往是最后退出的!

1.2.4 线程分离

默认情况下,新创建的线程是joinable的,线程退出后需要对其进型pthread_join操作,否则无法释放资源从而造成系统泄漏。如果不关心线程的返回值的话join就是一种负担。这个时候我们可以告诉系统,当线程退出时,自动释放线程资源。

int pthread_detach(pthread_t thread);
//功能:进行线程分离
//参数://thread:被分离的线程ID
//返回值:成功返回0;失败返回错误码

可以是线程组内其他线程对目标线程进型分离,也可以是线程自己分离。joinable和分离是冲突的,一个线程不能既是joinable又是分离的。

#include <iostream>
#include <unistd.h>
#include <pthread.h>
using namespace std;void *thread_run(void *arg)
{printf("%s\n", (char *)arg);return NULL;
}
int main(void)
{//创建线程pthread_t tid;pthread_create(&tid, NULL, thread_run, (void*)"thread1 run...") ;//分离线程pthread_detach(tid);int ret = 0;sleep(1); if (pthread_join(tid, NULL) == 0){printf("pthread wait success\n");ret = 0;}else{printf("pthread wait failed\n");ret = 1;}return ret;
}
caryon@VM-24-10-ubuntu:~/linux/thread$ ./thread 
thread1 run...
pthread wait failed

二、线程id与进程空间布局

在线程创建、终止、等待时我们都有注意到pthread_t thread(线程id)这个参数的存在,这个id表示的是什么意思呢?

#include<iostream>
#include<pthread.h>
using namespace std;void* run(void* args)
{while(true);return nullptr;    
}
int main()
{pthread_t tid;pthread_create(&tid,nullptr,run,(void*)"newthread");printf("0x%lx\n",tid);return 0;
}
caryon@VM-24-10-ubuntu:~/linux/thread$ ./thread 
0x7fae58e006c0

我们可以看到这个id的值是一个地址,那这个地址是什么地址呀?

通过ldd查看我们所形成的可执行程序是依赖pthread库的,这个库在程序运行时会加载到内存中,进而映射到进程地址空间里被所有的线程所共享。我们又知道linux系统中只有轻量级进程,线程是使用轻量级进程模拟实现的。但是用户想要查看当前线程的属性怎么办呢?
linux内核中是存在这些属性的,但是Linux中不存在线程呀!这需要内核层与用户层进行解耦啊!故而线程的相关属性也是由pthread库进行维护的,用户可以通过pthread库来查看线程的属性。

所以这个地址就是该线程的属性所对应的进程地址空间中的地址!

我们可以使用下面这个函数获取当前线程的id:

pthread_t pthread_self(void);

在这里插入图片描述
上图就是进程地址空间中的tcb了。
struct pthread
这个结构里面一定封装了LWP。
线程栈
进程地址空间中的栈是主线程的栈,新线程的栈是通过动态申请创建的。
线程局部存储
理论上来说全部变量是所有线程所共享的,即他们所访问的全局变量的地址是相同的!但是在声明全局变量是加上__thread进行修饰(修饰的只能是内置类型)就表示给每个线程都来一份,即线程的局部性存储。

#include<iostream>
#include<pthread.h>
using namespace std;__thread int count=100;void* run(void* args)
{printf("new thread &count : %p\n",&count);return nullptr;    
}int main()
{pthread_t tid;pthread_create(&tid,nullptr,run,(void*)"newthread");pthread_join(tid,nullptr);printf("main thread &count : %p\n",&count);return 0;
}
caryon@VM-24-10-ubuntu:~/linux/thread$ ./thread 
new thread &count : 0x71e23b2006bc
main thread &count : 0x71e23ba8e4fc

三、线程的封装

#pragma once#include <iostream>
#include <string>
#include <pthread.h>
#include <functional>
#include <sys/types.h>
#include <unistd.h>using func_t = std::function<void()>;
static int number = 1;
enum class TSTATUS
{NEW,RUNNING,STOP
};class Thread
{
private:// 成员方法!static void *Routine(void *args){Thread *t = static_cast<Thread *>(args);t->_status = TSTATUS::RUNNING;t->_func();return nullptr;}void EnableDetach() { _joinable = false; }bool IsJoinable() { return _joinable; }
public:Thread(func_t func) : _func(func), _status(TSTATUS::NEW), _joinable(true){_name = "Thread-" + std::to_string(number++);_pid = getpid();}bool Start(){if (_status != TSTATUS::RUNNING){int n = ::pthread_create(&_tid, nullptr, Routine, this); if (n != 0)return false;return true;}return false;}bool Stop(){if (_status == TSTATUS::RUNNING){int n = ::pthread_cancel(_tid);if (n != 0)return false;_status = TSTATUS::STOP;return true;}return false;}bool Join(){if (_joinable){int n = ::pthread_join(_tid, nullptr);if (n != 0)return false;_status = TSTATUS::STOP;return true;}return false;}void Detach(){EnableDetach();pthread_detach(_tid);}~Thread(){}
private:std::string _name;pthread_t _tid;pid_t _pid;bool _joinable; // 是否是分离的,默认不是func_t _func;TSTATUS _status;
};

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

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

相关文章

Aliyun CTF 2025 web 复现

文章目录 ezoj打卡OKoffens1veFakejump server ezoj 进来一看是算法题&#xff0c;先做了试试看,gpt写了一个高效代码通过了 通过后没看见啥&#xff0c;根据页面底部提示去/source看到源代码&#xff0c;没啥思路&#xff0c;直接看wp吧&#xff0c;跟算法题没啥关系,关键是去…

Git使用(一)--如何在 Windows 上安装 Git:详细步骤指南

如果你想在 Windows 机器上安装 Git&#xff0c;可以按照以下详细指南进行操作。 第一步&#xff1a;下载 Git 可通过官网下载 适用于 Windows 的 Git 最新版本。 如果下载速度较慢&#xff0c;可以通过下面提供的百度网盘 链接下载安装包&#xff0c; https://git-scm.com/d…

本地Git仓库搭建(DevStar)与Git基本命令

本地Git仓库搭建&#xff08;DevStar&#xff09;与Git基本命令 实验环境搭建平台Git基本命令的使用本地仓库的创建代码提交代码合并版本发布 总结 实验环境 搭建平台 按照DevStar的Github仓库要求&#xff0c;在终端中执行下列命令&#xff0c;即可成功安装DevStar到本地部署…

stm32 蓝桥杯 物联网 独立键盘的使用

在蓝桥杯物联网平台里面&#xff0c;有5个外接设备&#xff0c;其中有一个就是6个独立按键。首先&#xff0c;我们先看一下按键有关的电路图。 电路图与cubemx设定 由图可见&#xff0c;独立键盘组由两行三列构成&#xff0c;我们通过行列来锁定要访问的独立按键在哪。ROW1挂…

工作记录 2017-01-06

工作记录 2017-01-06 序号 工作 相关人员 1 协助BPO进行Billing的工作。 修改CSV、EDI837的导入。 修改邮件上的问题。 更新RD服务器。 郝 修改的问题&#xff1a; 1、 In “Full Job Summary” (patient info.), sometime, the Visit->Facility is missed, then …

Python Selenium库入门使用,图文详细。附网页爬虫、web自动化操作等实战操作。

文章目录 前言1 创建conda环境安装Selenium库2 浏览器驱动下载&#xff08;以Chrome和Edge为例&#xff09;3 基础使用&#xff08;以Chrome为例演示&#xff09;3.1 与浏览器相关的操作3.1.1 打开/关闭浏览器3.1.2 访问指定域名的网页3.1.3 控制浏览器的窗口大小3.1.4 前进/后…

SpringMVC 基本概念与代码示例

1. SpringMVC 简介 SpringMVC 是 Spring 框架中的一个 Web 层框架&#xff0c;基于 MVC&#xff08;Model-View-Controller&#xff09; 设计模式&#xff0c;提供了清晰的分层结构&#xff0c;适用于 Web 应用开发 SpringMVC 主要组件 DispatcherServlet&#xff08;前端控…

DeepSeek结合Mermaid绘图(流程图、时序图、类图、状态图、甘特图、饼图)转载

思维速览&#xff1a; 本文将详细介绍如何利用DeepSeek结合Mermaid语法绘制各类专业图表&#xff0c;帮助你提高工作效率和文档质量。 ▍DeepSeek入门使用请看&#xff1a;deepseek保姆级入门教程&#xff08;网页端使用 本地客户端部署 使用技巧&#xff09; DeepSeek官网…

上下分层、左右分离的驱动设计思想

之前了解了最简单的驱动程序、但是不易扩展、现在继续学习、上下分层、左右分离的驱动设计思想。 1、led_dev.c函数 上层函数&#xff0c;①定义一个结构体&#xff0c;存储函数用来接应app的函数。②定义一个入口函数&#xff0c;将我们接应的函数告诉内核&#xff0c;给这个…

《历史代码分析》5、动态控制列表的列

​​ 本系列《历史代码分析》为工作中遇到具有代表性的代码。今天我们讲一下&#xff0c;动态展示列表的列&#xff0c;因为找不到代码了&#xff0c;所有本篇用图展示。 举个栗子 ​​ 我们希望能够动态的控制列表的列&#xff0c;例如&#xff0c;英语老师只想知道自己学…

Windows HD Video Converter Factory PRO-v27.9.0-

Windows HD Video Converter Factory PRO 链接&#xff1a;https://pan.xunlei.com/s/VOL9TaiuS7rXbu-1kEDndoceA1?pwd7qch# 支持300多种视频格式转换&#xff0c;在保留视频质量的同时&#xff0c;压缩率可达80%&#xff0c;转换速度可达50X速率&#xff01; 支持画面剪切、片…

##Hive安装-初始化元数据报错 *** schemaTool failed ***

报错&#xff1a; org.apache.hadoop.hive.metastore.HiveMetaException: Failed to get schema version. Underlying cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException : Communications link failure 解决方案&#xff1a; 尝试一&#xff1a;javax.jdo.o…

远程手机遥控开关原理及应用

远程手机遥控开关的工作原理主要是通过互联网传递无线信号&#xff0c;控制用电器的一种智能家居产品。 远程手机遥控开关的基本套件包括&#xff1a;手机APP、网线、家用WIFI中转无服务器或者是工厂提供的自带网线端口的中转服务器、连接用电器的接收器。使用时&#xff0c;手…

Mac java全栈开发环境配置

前言 由于最近手中的windows本子坏了,所以搞了一台m系列的macbookpro 作为一个开发者 面对新设备最先考虑的应该就是各种sdk、中间件服务、环境变量配置和工具了吧!!! 本文将带你手把手学习Mac搭建属于自己的本地开发环境 安装brew 什么是brew? ‌Brew(全称Homebrew)…

HTMLCSS绘制三角形

1.代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>01triangle</title><s…

vue3-element-admin 前后端本地启动联调

一、后端环境准备 1.1、下载地址 gitee 下载地址 1.2、环境要求 JDK 17 1.3、项目启动 克隆项目 git clone https://gitee.com/youlaiorg/youlai-boot.git数据库初始化 执行 youlai_boot.sql 脚本完成数据库创建、表结构和基础数据的初始化。 修改配置 application-dev.y…

WinForm模态与非模态窗体

1、模态窗体 1&#xff09;定义&#xff1a; 模态窗体是指当窗体显示时&#xff0c;用户必须先关闭该窗体&#xff0c;才能继续与应用程序的其他部分进行交互。 2&#xff09;特点&#xff1a; 窗体以模态方式显示时&#xff0c;会阻塞主窗体的操作。用户必须处理完模态窗体上…

Agisoft Metashape 创建分块建模

Agisoft Metashape 创建分块建模 文章目录 Agisoft Metashape 创建分块建模前言一、构建分块模型1.1、设置模型范围1.2、参数设置二、构建纹理三、导出分块模型3.1整体导出3.2单独导出选定的分块四、编辑分块模型前言 从 Agisoft Metashape Professional 的 2.1. 版本开始,就…

MinIO的预签名直传机制

我们传统使用MinIo做OSS对象存储的应用方式往往都是在后端配置与MinIO的连接和文件上传下载的相关接口&#xff0c;然后我们在前端调用这些接口完成文件的上传下载机制&#xff0c;但是&#xff0c;当并发量过大&#xff0c;频繁访问会对后端的并发往往会对服务器造成极大的压力…

手把手教你用Docker搭建gitlab

文章目录 前言一、安装Docker二、安装GItlab三、配置Gitlab四、备份五、Docker数据持久化总结 前言 如题所述&#xff0c;手把手带你搭建gitlab&#xff0c;目标是实现ssh链接clone项目&#xff0c;不会我随你怎么说。 说正题&#xff0c;GitLab 是一个基于 Git 的全面 DevOps…