Linux多线程-概念和控制
零、前言
一、Linux线程概念
1、什么是线程
- 概念:
- 以整个运行视角理解:
- 示图:

- 如何理解之前所说的’进程’:
- 注意:
2、vfork函数/pthread线程库
- vfork函数原型:
pid_t vfork(void);
- 注意:
示例:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
int val=100;
pid_t id=vfork();
if(id==0)
{
//child
int cnt=0;
while(1)
{
printf("i am child pid:%d ppid:%d val:%d &val:%p\n",getpid(),getppid(),val,&val);
cnt++;
sleep(1);
if(cnt==2)
val=200;
if(cnt==5)
exit(0);
}
}
else if(id>0)
{
//father
int cnt=0;
while(1)
{
printf("i am father pid:%d ppid:%d val:%d &val:%p\n",getpid(),getppid(),val,&val);
cnt++;
sleep(1);
if(cnt==3)
val=300;
}
}
return 0;
}
- 效果:

- 原生线程库pthread:
3、线程优缺点及其他分析
- 线程的优点:
- 注意:
- 线程的缺点:
- 线程异常:
- 线程用途:
二、Linux进程VS线程
1、进程和线程
- 概念:
- 线程共享进程数据,但也有线程自己独有的数据:
- 线程中共享的数据:
- 进程和线程的关系图:

三、Linux线程控制
1、POSIX线程库
- pthread线程库是应用层的原生线程库:
- 错误检查:
2、线程创建
- pthread_create函数原型:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);
- 解释:
- 注意:
- 示例:
mypthread.c:
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
int val=0;
void* Routine(void* avgs)
{
while(1)
{
printf("I am %s... val:%d\n",(char*)avgs,val);
sleep(1);
}
}
int main()
{
pthread_t tid1,tid2,tid3;
int ret1=pthread_create(&tid1,NULL,Routine,(void*)"pthread 1");
if(ret1!=0)
{
fprintf(stderr,"pthread_creat:%s\n",strerror(ret1));
exit(1);
}
int ret2=pthread_create(&tid2,NULL,Routine,(void*)"pthread 2");
if(ret2!=0)
{
fprintf(stderr,"pthread_creat:%s\n",strerror(ret2));
exit(1);
}
int ret3=pthread_create(&tid3,NULL,Routine,(void*)"pthread 3");
if(ret3!=0)
{
fprintf(stderr,"pthread_creat:%s\n",strerror(ret3));
exit(1);
}
while(1)
{
printf("I am main pthread...val:%d\n",val++);
sleep(1);
}
return 0;
}
Makefile:
mypthread:mypthread.c
gcc -o $@ $^ -pthread
.PHONY:clean
clean:
rm -f mypthread
- 效果:

- 查看线程信息:ps -aL

- 注意:
3、线程ID及线程地址空间布局
- 概念:
- pthread_ self函数原型:
pthread_t pthread_self(void);
- 示图:

4、线程终止
- 终止线程的三种方法:
- pthread_exit函数原型:
void pthread_exit(void *value_ptr);
- 解释:
- pthread_cancel函数原型:
int pthread_cancel(pthread_t thread);
- 解释:
示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
void *thread1(void *arg)
{
printf("%s returning ... \n",(char*)arg);
int *p = (int*)malloc(sizeof(int));
*p = 1;
return (void*)p;
}
void *thread2(void *arg)
{
printf("%s exiting ...\n",(char*)arg);
int *p = (int*)malloc(sizeof(int));
*p = 2;
pthread_exit((void*)p);
}
void *thread3(void *arg)
{
while ( 1 ){ //
printf("%s is running ...\n",(char*)arg);
sleep(1);
}
return NULL;
}
int main( void )
{
pthread_t tid;
void *ret;
// thread 1 return
pthread_create(&tid, NULL, thread1, (void*)"thread 1");
pthread_join(tid, &ret);
printf("thread 1 return, thread id %X, return code:%d\n", tid, *(int*)ret);
free(ret);
// thread 2 exit
pthread_create(&tid, NULL, thread2, (void*)"thread 2");
pthread_join(tid, &ret);
printf("thread 2 exit, thread id %X, return code:%d\n", tid, *(int*)ret);
free(ret);
// thread 3 cancel by other
pthread_create(&tid, NULL, thread3, (void*)"thread 3");
sleep(3);
pthread_cancel(tid);
pthread_join(tid, &ret);
if (ret == PTHREAD_CANCELED)
printf("thread 3 cancel, thread id %X, return code: PTHREAD_CANCELED->%d\n", tid,ret);
else
printf("thread return, thread id %X, return code:%d\n", tid,ret);
return 0;
}
- 效果:

5、线程等待
- 为什么需要线程等待:
- pthread_join函数原型:
int pthread_join(pthread_t thread, void **value_ptr);
- 解释:
- 注意:
- 终止获取的状态情况:
- 示图:

- 示例:
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
int val=0;
struct Ret
{
int exitno;
int exittime;
//...
};
void* Routine(void* avgs)
{
int cnt=1;
while(1)
{
printf("I am %s... val:%d\n",(char*)avgs,val);
sleep(1);
cnt++;
if(cnt==3)
{
struct Ret* p=(struct Ret*)malloc(sizeof(struct Ret));
p->exitno=0;
p->exittime=6666;
pthread_exit((void*)p);
//pthread_cancel(pthread_self());
}
}
}
int main()
{
pthread_t tid1,tid2,tid3;
pthread_create(&tid1,NULL,Routine,(void*)"pthread 1");
pthread_create(&tid2,NULL,Routine,(void*)"pthread 2");
pthread_create(&tid3,NULL,Routine,(void*)"pthread 3");
int cnt=0;
while(1)
{
printf("I am main pthread...val:%d\n",val++);
sleep(1);
cnt++;
if(cnt==3)
break;
}
printf("wait for pthread...\n");
void* ret;
pthread_join(tid1,&ret);
printf("pthread id:%x exitno:%d exittime:%d\n",tid1,((struct Ret*)ret)->exitno,((struct Ret*)ret)->exittime);
pthread_join(tid2,&ret);
printf("pthread id:%x exitno:%d exittime:%d\n",tid2,((struct Ret*)ret)->exitno,((struct Ret*)ret)->exittime);
pthread_join(tid3,&ret);
printf("pthread id:%x exitno:%d exittime:%d\n",tid3,((struct Ret*)ret)->exitno,((struct Ret*)ret)->exittime);
return 0;
}
- 效果:

6、线程分离
- 概念:
- pthread_detach函数原型:
int pthread_detach(pthread_t thread);
- 注意:
- 示例:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* Routine (void* arg)
{
pthread_detach(pthread_self());
printf("%s detach success!\n");
int cnt=0;
while(cnt<5)
{
cnt++;
printf("%s running...\n",(char*)arg);
sleep(1);
}
printf("%s return...\n");
return NULL;
}
int main()
{
pthread_t tid;
pthread_create(&tid,NULL,Routine,(void*)"thread");
sleep(2);//等待线程分离
void* ret;
if(pthread_join(tid,&ret)==0)
printf("thread join success! ret:%d\n",(int*)ret);
else
printf("thread join fail... ret:%d\n",(int*)ret);
return 0;
}
- 效果:
