今天学习的都是linux线程库中的函数。
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
参数
返回值
void pthread_exit(void *value_ptr);
参数:
返回值:
这个函数类似于线程函数返回,可以说是等同于return。子进程退出正常退出不影响其他线程
但是主线程调用该函数的时候,与return有极大的区别。
主线程pthread_exit退出
int pthread_cancel(pthread_t thread)
参数:
返回值:
和pthread_exit一样,子终止,主进程不影响,主进程终止,子进程不影响。
pthread_t pthread_self(void);
无需传参,哪个线程调用就返回该线程id。
配合使用:pthread_cancel(pthread_self());//中止当前进程。
int pthread_join(pthread_t thread, void **value_ptr);
参数:
返回值:成功返回0;失败返回错误码
就是线程结束的时候返回值可以用join的第二个参数保持。
void*function(void*ags)
{
int cnt=0;
int*data=new int[5];
while(1)
{
sleep(1);
data[cnt]=cnt;
cout<<"new thread cnt:"<
主进程以阻塞的方式等待编号为tid的线程退出。可以以非阻塞的方式等待退出吗?不可以。
无视线程,对线程分离。
int pthread_detach(pthread_t thread);
参数:
返回值:
可以是线程组内其他线程对目标线程进行分离,也可以是线程自己分离:
pthread_detach(pthread_self());
joinable和分离是冲突的,一个线程不能既是joinable又是分离的。
void*function(void*ags)
{
pthread_detach(pthread_self());
sleep(1);
return nullptr;
}
int main()
{
pthread_t tid;
pthread_t maintid=pthread_self();
pthread_create(&tid,nullptr,function,(void*)maintid);
sleep(2);
int n=pthread_join(tid,nullptr);
cout<<"n:"<
分离的线程不可以被主线程等待,但是分离的线程也是整个进程的线程,一旦异常也会对整个进程造成影响。
int pthread_kill(pthread_t thread, int sig);
参数:
返回值:
与kill系统函数不同,如果用kill发送信号给同进程的其他线程,那么也只会自己接收到,而pthread_kill则是精准的发送给对应的线程。
int main()
{
pthread_t tid=pthread_self();
printf("tid:%d 16进制tid:%p \n",tid,tid);
//。。。。。。
}
看起来我们的tid好像一个地址信息。
其实tid就是地址信息,对应的线程其实是操作系统在进程的共享区开辟的一块空间,一份线程一份空间,我们的tid线程id其实是线程空间的起始地址。
不同的线程在运行期间调用着不同的函数在系统中运行,但是栈区只有一个,每个线程的函数栈帧也不同,一个栈区无法满足多个线程同时运行,所以OS就在地址空间的共享区中,开辟了子线程的自己的栈区,而原先的栈区在多线程与单线程下都是给主线程来运行的。
线程也有着自己的局部存储空间,保存这一些私有的数据。
我们定义一个全局变量,然后子线程与主线程同时打印数据与地址,然后子线程修改全局变量,然后继续打印。
int g_val=0;
void*childfunction(void*ags)
{
int cnt=0;
while(1)
{
printf("child thread g_val:%d &g_val:%p cnt:%d\n",g_val,&g_val,++cnt);
if(cnt==5)
{
printf("child change data\n");
g_val=1;
}
sleep(1);
}
return nullptr;
}
int main()
{
pthread_t tid;
pthread_create(&tid,nullptr,childfunction,nullptr);
while(1)
{
printf("main thread g_val:%d &g_val:%p\n",g_val,&g_val);
sleep(1);
}
//........
}
父子线程共享该全局变量,如果不想共享数据,可以在全局变量前加修饰符__thread。这个时候在编译的时候就会在子线程共享区中生成私有的全局变量。
__thread int g_val=0;
但是观察发现,似乎主线程的全局数据地址也在共享区,的确主线程也有着自己的线程结构体。