欢迎光临
我们一直在努力

【Linux】线程控制(二)

文章目录

  • 背景
  • 🚩进程控制
  • 线程计算1-100
  • 🚩线程库
  • c++11多线程

背景

Linux中没有真正的线程概念,而是复用进程数据结构和管理算法,用进程模拟线程

只有轻量级进程,不会提供线程的调用接口,而是提供轻量级进程的系统调用接口

但是我们用户需要线程调用,所以有pthread库帮我们封装了轻量级进程调用接口,我们可以直接使用线程接口

  • 每个linux平台自带pthread库,
  • 编写多线程代码需要pthread库

线程接口

在这里插入图片描述 每个线程都有自己的ID, ⭐pthread_create不是系统调用,需链接 -pthread

🚩进程控制

快速使用一下

#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;
void* threadRoutine(void *args)
{
const char* str=(const char*)args;
cout<<str<<endl;
int cnt=5;
while(cnt)
{
cout<<"thread id :"<< pthread_self() <<endl;
sleep(1);
}
}
int main()
{
pthread_t tid;
cout<<tid<<endl;
pthread_create(&tid,nullptr,*threadRoutine,(void*)"thread 1");
cout<<tid<<endl;
pthread_join(tid,nullptr);
return 0;
}

在这里插入图片描述

刚开始tid没有初始化,主线程要最后一个退出,等待子线程

线程等待默认是阻塞的,为什么不考虑异常呢? 因为单个线程如果异常,整个进程都崩溃了

int g_val=100;
void* threadRoutine(void* args)
{
const char* str=(const char*)args;
int cnt=5;
while(cnt)
{
printf("%s pid: %d, g_val: %d, &g_val: 0x%p \\n",str,getpid(),g_val,&g_val);
sleep(1);
g_val++;
}
//pthread_exit(100)
//exit(100); //不能用exit,直接把整个进程退出了
return (void*)100;//退出线程
}
int main()
{
pthread_t tid;
pthread_create(&tid,nullptr,*threadRoutine,(void*)"thread 1");
int cnt=5;
while(cnt)
{
printf("main thread %d, g_val: %d, &g_val: 0x%p , create a new thread: %p \\n",getpid(),g_val,&g_val, tid);
sleep(1);
g_val++;
}
sleep(2);
void* set;
pthread_join(tid,&set);
cout<<"new thread quit success"<<(long long int)set<<endl;
return 0;
}

ps -aL查看所有线程 while :; do ps -aL; sleep 1;done;监控

在这里插入图片描述 可以看到两个mythread,进程pid相同,LWP(light weight process轻量化进程)不同

  • LWP在内核看来就是线程

线程ID有两种:一种是内核视角LWP,另一种线程视角pthread_t

在这里插入图片描述 两个不同的执行流,共享相同的全局变量,也可以调用相同的函数,这里发生数据冲突了,后面会讲

所以,用户级线程(线程库控制)加上内核LWP才构成Linux线程,Linux也有内核级线程 用户级执行流:LWP=1:1 在这里插入图片描述

线程计算1-100

class Reques
t
{
public:
Request(int begin,int end,const string& threadname)
:_begin(begin),
_end(end),
_threadname(threadname)
{}
public:
int _begin;
int _end;
string _threadname;
};

class Reponse
{
public:
Reponse(int result,int exitcode)
:_result(result),
_exitcode(exitcode)
{}
public:
int _result; //计算结果
int _exitcode;//计算结果是否可靠
};

void* sumRoutine(void* args) // 线程的参数和返回值,不仅仅可以传递一般参数,还可以传递自定义对象
{
Request* rq=static_cast<Request*>(args); //(Request*)args;
Reponse* rsp=new Reponse(0,0);
if(rq->_begin>rq->_end)
{
rsp->_exitcode=1;
}
else{
for(int i=rq->_begin;i<=rq->_end;i++)
{
rsp->_result+=i;
}
}
delete rq;
return rsp;
}
int main()
{
pthread_t tid;
Request *rq=new Request(1,100,"thread 1");
pthread_create(&tid,nullptr,*sumRoutine,rq);

void* set;
pthread_join(tid,&set);
Reponse *rsp=static_cast<Reponse*>(set);
cout<<"rsp -> _result: "<<rsp->_result<<"rsp ->_exitcode: "<<rsp->_exitcode <<endl;
delete rsp;
return 0;
}

在这里插入图片描述

🚩线程库

线程的概念是库给我们维护的,线程库中有clone回调函数将执行流给进程PCB,共享父进程资源,线程库维护线程概念,不用维护执行流,线程库注定要维护多个线程属性集合,先描述再组织

线程库要不要加载到内存? 要,加载到共享区,等于动态库 在这里插入图片描述

在这里插入图片描述

c++11多线程

C++11也支持多线程了,已经帮我们封装好了,直接用就行

void threadrun()
{
while(true)
{
cout << "I am a new thead for C++" << endl;
sleep(1);
}
}

int main()
{
thread t1(threadrun);

t1.join();

return 0;
}

赞(0)
未经允许不得转载:171主机测评 » 【Linux】线程控制(二)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址