陈坤做直播在哪个网站,红旗河沟网站建设,类似于wordpress,wordpress同步发布对线程的控制思路和进程相似#xff0c;创建、等待、终止#xff0c;只需要调用接口就行。但是在Linux下没有线程的概念#xff0c;因为Linux的设计者认为#xff0c;线程是一种轻量级的进程#xff0c;毕竟创建线程只需要创建PCB。因此Linux中使用多线程必须使用第三方pt…对线程的控制思路和进程相似创建、等待、终止只需要调用接口就行。但是在Linux下没有线程的概念因为Linux的设计者认为线程是一种轻量级的进程毕竟创建线程只需要创建PCB。因此Linux中使用多线程必须使用第三方pthread库线程库为用户提供接口。 线程的创建——pthread_create 参数
tread是线程标识符的指针类似进程pid
attr是线程属性一般是nullptr
start_routine是线程执行的函数
arg是传递给线程函数的参数
返回值 线程的终止
线程终止有三种方式 1.线程函数执行return就会结束进程 2.线程函数使用pthread_exit接口 3.一个线程中使用pthread_cancel接口终止另一个进程 线程的等待——pthread_join 参数 thread是线程标识符
retval是标识符对应线程退出后的返回值是一个输出型参数。因为线程函数的返回值是void*类型所以参数类型必须是void** 分离线程——pthread_detach
如果说线程的返回值我们不关心使用join对操作系统是一种负担但是不等待线程也会造成内存泄漏。使用这个接口就不用等待线程在线程执行完自动回收。 分离线程既可以在其他线程分离也可以自己分离
其他线程传入要分离的线程ID自己分离调用pthread_self()获取线程tid即可 进程控制的例子
#include iostream
#include pthread.h
#include string
#include unistd.h
using namespace std;
//使用线程实现从a到b的累加
class Request
{
public:int _start;int _end;string _threadname;Request(int start, int end, string name):_start(start),_end(end),_threadname(name){}
};class Response
{
public:int _val;int _exitcode;Response(int val, int exitcode):_val(val),_exitcode(exitcode){}
};void* cal(void* arg)
{Request* rq (Request*)arg;Response* rsp new Response(0, 0);for(int i rq-_start; i rq-_end; i){usleep(100000);rsp-_val i;cout rq-_threadname pid: getpid() operate : ret i endl;}//线程间共用堆把主线程的数据释放delete rq;return rsp;
}int main()
{pthread_t tid;Request* rq new Request(0,50,mythread);//创建线程cout main thread pid: getpid() create thread endl;pthread_create(tid, nullptr, cal, (void*)rq);void* ret;//等待线程,获取结果pthread_join(tid, ret);Response* rsp (Response*)ret;cout rq-_threadname cal ret rsp-_val exitcode rsp-_exitcode endl; delete rsp;return 0;
} 使用线程库编译时要用-lpthread选项声明使用的库 通过指令看到线程的PID相同因为它们都是同一个进程的执行流资源LWP是线程标识符不同线程互不相同 线程ID
我们知道LInux系统没有线程概念线程这个概念是由线程库来维护的线程库调用了系统调用接口clone clone是创建进程的接口fork的底层也使用了它线程库对其封装提供可以创建线程的接口。那么线程库必然会对建立的所有线程进行管理就像操作系统管理进程一样创建对应的TCB等等。 线程库是一个动态库进程运行时会加载到共享区。库中就有线程对应的数据结构这些数据结构都被存储到一个数组中数组中每个线程的数据结构的地址就是它的tid
从上面的动态库结构看到线程有自己独立的栈和局部存储。 线程栈
独立性
线程栈相互独立也就是说每个线程即使使用了相同的线程函数创建的变量也是互不相同的。
#include iostream
#include pthread.h
#include vector#define NUM 4//线程数量
using namespace std;void* fun(void* arg)
{int val 10;return (void*)val;//返回栈中变量地址
}int main()
{ vectorpthread_t tids;//创建多个线程for(int i 0; i NUM; i){pthread_t tid;pthread_create(tid, nullptr, fun, nullptr);tids.push_back(tid);}//查看栈中变量地址for(auto e : tids){void* ret;pthread_join(e, ret);cout (int*)ret endl;}return 0;
} 可见性
虽然栈是相互独立的但是并不意味着栈中的数据对其他线程是不可访问的(实际应用中不推荐这种访问)
#include iostream
#include pthread.h
#include vector
#include unistd.h
using namespace std;
int* addr;
void* fun(void* arg)
{int val 0;addr val;int cnt 10;//循环打印valwhile(cnt--){sleep(1);cout val: val endl;}return nullptr;
}
int main()
{//创建线程pthread_t tid;pthread_create(tid, nullptr, fun, nullptr);//修改valsleep(4);cout main change val: 10 endl;*addr 10;pthread_join(tid, nullptr);return 0;
} 线程局部存储
一个进程的全局变量对所有的线程都是可见的如果想要一个线程独有的全局变量可以使用线程局部存储。
在全局变量定义的前面加上 __thread
#include iostream
#include pthread.h
#include vector
#include unistd.husing namespace std;
__thread int gval 0;void *fun1(void *arg)
{gval 100;cout gval gval endl;return nullptr;
}void *fun2(void *arg)
{gval 200;cout gval gval endl;return nullptr;
}
int main()
{vectorpthread_t tids;pthread_t tid;pthread_create(tid, nullptr, fun1, nullptr);tids.push_back(tid);pthread_create(tid, nullptr, fun2, nullptr);tids.push_back(tid);for (auto e : tids){pthread_join(e, nullptr);}return 0;
}