Linux系统编程:多线程编程

本文介绍了Linux系统编程中的多线程概念,包括线程的并发执行、共享变量以及线程合并。通过实例展示了如何创建并发线程,以及线程间如何共享和修改全局及局部变量。同时,讨论了线程合并的重要性,以确保主进程等待子线程完成,避免生存周期问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 什么是线程

线程是比进程更小的能独立运行的基本单位,线程基本上不拥有系统资源

一个进程下可以开多个线程,这些线程是并发的

在这里插入图片描述查看线程命令

命令含义
ps -T -p -T开启线程查看
top -H -p -H开启线程查看

文件书写

文件含义
/proc/{PID}/task/线程默认的名字和进程名相同
/proc/{PID}/task/{tid}/comm线程名

2. 操作

操作函数
线程标识pthread_t pthread_self(void)
线程创建int pthread_create(pthread_t * tidp, pthread_attr_t * attr, void *(*start_rtn)(void), void * arg)
子线程终止void pthread_exit(void* retval)
线程合并int pthread_join(pthread_t tid, void **retval)
线程分离int pthread_detach(pthread_t tid)
发送信号int pthread_kill(pthread_t tid, int sig)

线程标识 pthread_self()

线程创建 pthread_create(线程id指针 , NULL, 函数指针, 函数参数)

2.1 线程的并发

创建一个线程,让主进程和这个线程并发执行:

#include <pthread.h>
#include <unistd.h>
#include <iostream>
using namespace std;

void* handle(void*){
        for(int i=0;i<10;++i){
                sleep(1);
                cout << pthread_self() << ":" << i << endl;
        }
        return NULL;
}

int main(){
        cout << getpid() << endl;             // pid
        cout << pthread_self() << endl;       // 线程标识

        pthread_t tid;
        pthread_create(&tid,NULL,handle,NULL);     // 创建一个线程,handle传指针并返回指针,是这个线程做的事

        // 主进程也做这个
        for(int i=0;i<10;++i){
                sleep(1);
                cout << pthread_self() << ":" << i << endl;
        }
}

结果为:

[root@foundation1 C++7.13]# g++ thread.cpp -pthread
[root@foundation1 C++7.13]# ./a.out
7423
140021348697920
140021348697920:0
140021330745088:0
140021330745088140021348697920::11

140021330745088:2
140021348697920:2
140021330745088:3
140021348697920:3
140021330745088140021348697920:4:4

140021348697920140021330745088:5:5

140021348697920:6
140021330745088:6
140021348697920140021330745088:7:7

140021348697920140021330745088::8
8
140021330745088140021348697920::99

可以发现两个是并发的

在另一个窗口看所有线程ps -T -ef可以发现,两个进程id是一样的,线程id不同
在这里插入图片描述

2.2 共用变量

同一个进程中两个线程可以共用全局变量,也可以共用局部变量:

#include <pthread.h>
#include <unistd.h>
#include <iostream>
using namespace std;

void* handle(void* p){
        int* pn = (int*)p;
        for(int i=0;i<10;++i){
                sleep(1);
                cout << pthread_self() << ":" << --*pn << endl;       // 对n减
        }
        return NULL;
}

int main(){
        cout << getpid() << endl;
        cout << pthread_self() << endl;

        int n = 5;             // 定义局部变量
        pthread_t tid;
        pthread_create(&tid,NULL,handle,&n);     // 这里需要传参

        // 主进程
        for(int i=0;i<10;++i){
                sleep(1);
                cout << pthread_self() << ":" << ++n << endl;       // 对n加
        }
}

结果为:

[root@foundation1 C++7.13]# g++ thread.cpp -pthread
[root@foundation1 C++7.13]# ./a.out
7818
139961303992128
139961303992128139961286039296::4
5
139961286039296139961303992128::45

139961286039296139961303992128::54

139961286039296139961303992128::45

139961303992128139961286039296::56

139961303992128139961286039296::56

139961286039296139961303992128::54

139961303992128139961286039296::56

139961286039296139961303992128::54

139961286039296139961303992128::54

可以发现两个线程对同一个n加减,表明变量是共用

2.3 线程合并

有时候主进程已经结束了,但子线程还没有跑完,整个程序就结束了
我们可以使用
线程合并 pthread_join( 线程id, 返回值)
让主进程等待子线程跑完

有时变量的生存周期结束后还没有完全释放,使用动态申请内存避免这种情况

#include <pthread.h>
#include <unistd.h>
#include <iostream>
using namespace std;

void* handle(void* p){
        int* pn = (int*)p;
        for(int i=0;i<10;++i){
                sleep(1);
                cout << pthread_self() << ":" << --*pn << endl;
        }
        delete pn;                          // 到这里再释放
        // pthread_exit();
        return NULL;
}

// 创建线程
pthread_t test(){
        int* p = new int(3);         // 从这里申请,初始值为3
        pthread_t tid;
        pthread_create(&tid,NULL,handle,p);
        return tid;
}

int main(){
        cout << getpid() << endl;
        cout << pthread_self() << endl;

        pthread_t tid = test();
        int n = 5;
        // pthread_detach(tid);
        for(int i=0;i<5;++i){
                sleep(1);
                cout << pthread_self() << ":" << ++n << endl;
        }
        pthread_join(tid,NULL);                // 线程合并
        return 0;
}

结果为:

[root@foundation1 C++7.13]# g++ thread3.cpp -pthread
[root@foundation1 C++7.13]# ./a.out
11227
139954324326208
139954324326208139954306373376:2:
6
139954324326208139954306373376:7:1

139954324326208139954306373376:8:0

139954324326208139954306373376::-19

139954306373376:-2
139954324326208:10
139954306373376:-3
139954306373376:-4
139954306373376:-5
139954306373376:-6
139954306373376:-7

主进程n从5开始递增5次,线程p从3开始递减10次,但主进程会等线程完成,并且不会出现生存周期的问题

通过返回多个值的方式,使用同一个值
也可以用同一个数p,主进程p从3开始递增5次,线程p从3开始递减10次

#include <pthread.h>
#include <unistd.h>
#include <iostream>
using namespace std;

void* handle(void* p){
        int* pn = (int*)p;
        for(int i=0;i<10;++i){
                sleep(1);
                cout << pthread_self() << ":" << --*pn << endl;
        }
        delete pn;
        return NULL;
}

pair<pthread_t,int*> test(){
        int* p = new int(3);
        pthread_t tid;
        pthread_create(&tid,NULL,handle,p);
        return {tid,p};
}

int main(){
        cout << getpid() << endl;
        cout << pthread_self() << endl;

        auto [tid,p] = test();       // c++17   

        int n = 5;
        for(int i=0;i<5;++i){
                sleep(1);
                cout << pthread_self() << ":" << ++n << endl;
        }
        pthread_join(tid,NULL);
        return 0;
}

结果为:

[root@foundation1 C++7.13]# g++ thread2.cpp -pthread -std=c++17
[root@foundation1 C++7.13]# ./a.out
11325
140515561719616
140515543766784140515561719616::23

140515543766784:2
140515561719616:3
140515543766784140515561719616::23

140515543766784140515561719616::23

140515561719616140515543766784::23

140515543766784:2
140515543766784:1
140515543766784:0
140515543766784:-1
140515543766784:-2

并发过程中在2和3僵持,等待阶段开始递减

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值