Linux 线程实现

举报
IoT_Joker 发表于 2020/09/29 15:46:26 2020/09/29
【摘要】 目录一、概念二、线程实现1、创建并运行2、共同操作数据示例3、互斥对象mutex4、带参线程一、概念先了解一下进程,进程是系统中程序执行和资源分配的基本单位。每个进程有自己的数据段、代码段和堆栈段。而线程通常叫做 “轻量级进程”,一个进程可以有多个线程,它和同进程中的其他线程共享进程空间(堆代码、数据、文件描述符、信号等),只拥有自己的栈空间,关系如下图示例。线程也主要呈现三种状态:运行态、...

目录


一、概念

先了解一下进程,进程是系统中程序执行和资源分配的基本单位。每个进程有自己的数据段、代码段和堆栈段。
而线程通常叫做 “轻量级进程”,一个进程可以有多个线程,它和同进程中的其他线程共享进程空间(堆代码、数据、文件描述符、信号等),只拥有自己的栈空间,关系如下图示例。

线程也主要呈现三种状态:运行态、阻塞态、就绪态。
在同一个进程下,每个线程都有独立的ID,一般用tid表示。

二、线程实现

在c++11引入了一个多线程类std::thread,使用时需包含头文件<thread>
示例编译:g++ -std=c++11 -pthread thread.cpp -o thread

1、创建并运行

(1) 写一个普通函数,用来给线程执行

void t1(void){
    for(int i=0;i<10;i++){
        cout<<"this is thread1 + "<<i<<endl;
        sleep(1);
    }}

(2)创建线程

    thread thread1(t1);//创建

但是,创建之后线程不会立即运行,只有在join或detach指定运行方式之后才能运行。
(3)join或detach

#include <iostream>
#include <thread>
#include <unistd.h>
using namespace std;
void t1(void){
    for(int i=0;i<10;i++){
        cout<<"this is thread1 + "<<i<<endl;
        sleep(1);
    }}int main(int argc, char const *argv[]){
    /* code */
    thread thread1(t1);//创建
    cout<<"子线程之前"<<endl;
    thread1.join();
    //或者
    //thread1.detach();
    cout<<"主线程"<<endl;
    return 0;}

运行结果:
join方式


可以看到创建线程之后,子线程没有立即执行,但主线程执行了①,在join之后,可以看出,子线程运行了②,但主线程没有运行,直到子线程结束之后,主线程才执行了③。
因为join会使主线程阻塞,运行子线程,等到子线程结束,主线程才会继续运行。如下图所示。

detach方式


这时可以发现,使用detach方式之后,子线程的输出和主线程的输出会有重合的现象,并且,子线程明显没有完全执行完。
因为detach是一种让主线程和子线程并行运行的方式,并且主线程不会等到子线程执行完才结束,主线程运行结束,同时会连带着杀死子线程。如下图所示。

2、共同操作数据示例

#include <iostream>
#include <thread>
#include <unistd.h>
using namespace std;
int a=0;
void t1(void){
    for(int i=0;i<5;i++){
        sleep(1);
        cout<<"this is thread1 + "<<a++<<endl;
        sleep(1);
    }}void t2(void){
    for(int i=0;i<5;i++){
        cout<<"this is thread2 + "<<a++<<endl;
        sleep(2);
    }}int main(int argc, char const *argv[]){
    /* code */
    a=0;
    thread thread1(t1);//创建
    thread thread2(t2);
    cout<<"子线程之前"<<endl;
    thread1.join();
    thread2.join();
    cout<<"主线程"<<endl;
    return 0;}

两个线程可以共同操作变量a,运行结果:

但这是加入sleep规定了顺序,如果不加,输出会出现错误,极端情况下,a的值可能会重复输出,如下图所示。

这时可以使用互斥对象来避免。

3、互斥对象mutex

使用mutex需要包含头文件<mutex>,mutex可以保护一段代码完整的被执行

int a=0;
mutex mu;
void t1(void){
    for(int i=0;i<5;i++){
        mu.lock();
        cout<<"this is thread1 + "<<a++<<endl;
        mu.unlock();
    }}void t2(void){
    for(int i=0;i<5;i++){
        mu.lock();
        cout<<"this is thread2 + "<<a++<<endl;
        mu.unlock();
    }}

加入mutex运行结果:

4、带参线程

thread 线程名(线程函数名,参数列表);

#include <iostream>
#include <thread>
#include <unistd.h>
#include <mutex>
using namespace std;
void t1(const char *a){
    cout<<"线程参数:"<<a<<endl;}int main(int argc, char const *argv[]){
    /* code */
    thread thread1(t1,"arg");//创建
    cout<<"子线程之前"<<endl;
    thread1.join();
    cout<<"主线程"<<endl;
    return 0;}

运行结果:


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。