Linux 多线程编程(一)

 1、创建线程:
    有一个比较特殊的线程, 就是主线程或者称为初始线程,它是当一个进程被创建时创建的。而其他线程则是在初始线程中调用pthread_create创建的。创建的新线程初始为Ready状态,等待处理器调度。
2、执行线程:
    线程被创建后,就会执行phtread_create的start参数指定的函数,我们可以通过pthread_create的arg参数向线程开始函数传递一个参数,若不想传就直接赋值NULL。
上面提到了一个特殊的线程:初始线程,由操作系统Shell调用。操作系统先初始化进程,然后运行主线程的开始函数main。注意:初始线程和我们自己创建的线程有稍许不同:-开始函数参数不同,main的参数是int arg, char* argv,而我们自己的线程参数是void* arg。-自己创建的线程开始函数返回了,其它线程可以继续执行而初始线程开始函数main返回后进程会终止,导致其它正在运行的线程也就被强行终止若不想在main退出后关闭进程,可以在main最后调用pthread_exit,不过此时该进程就成了僵尸进程(defunct)直到所有线程执行完毕
如下程序,没有调用pthread_exit,初始线程退出时子线程也退出,当调pthread_exit后,主线程退出时,子线程仍然运行。

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>

void pthead_1()
{
  while(1)
  {
    printf("I am the child \n"); 
    sleep(1);
  } 
}

void main()
{
  pthread_t pthread_id;
 
  pthread_create(&pthread_id, NULL, &pthead_1, NULL);
  printf("I am the father!\n");
 
  sleep(2);
 
  pthread_exit(0);
 
}

pthread_exit函数使主线程退出。

-还有一个很重要的区别,多数系统上,初始线程使用的是进程的栈而自己创建的线程则使用自己的栈,往往自建线程的栈没有初始线程的栈空间大,要注意线程栈溢出哦!
 
3、 运行和阻塞 
    线程兄弟和我们一样,不能一直都醒着工作,它也要休息。线程一生大多处于三种状态:ready, running, 和blocked(和我一样,吃饭,工作,睡觉^_^)。线程被创建时出于就绪状态就绪状态等待处理器,处理器有空闲了,线程就转到运行状态疯狂工作,突然发现自己需要的其它资源(互斥量,条件变量)在别的线程手里,或者别的线程优先级比自己大一下从它手里抢走了处理器,或处理器烦了它了(时间片已经用完),或自己不好意思不干事还占用处理器了(等待I/O操作完成),就转换成阻塞状态,停止运行,可以休息下了。 休息可不是给它放长假,任务还没完成了...继续,当等待的资源得到满足,再次投入工作,进入运行状态。周而复始,直到任务完成。
4、 终止线程:
    线程一般都是在开始函数执行完时终止的。线程开始函数中调用pthread_exit或者其它线程调用pthread_cancel都可以终止线程终止后线程处于terminated状态(注意:不是destroyed),然后等待系统回收。若创建线程时指定线程是detached的,直接在线程开始函数执行完后就会被回收。
若是joinable,那就需要初始线程或其他线程调用pthread_join来等待要终止的线程了, 同时还可以通过pthread_joind的第二个参数获得线程的返回值。pthread_join后,线程就被detached //分离状态,然后被系统回收。
下面讨论几种线程终止情况:
 
1)、主线程等待子线程结束
    可以用pthread_join函数,pthread_join()函数会等待指定线程的结束,也就是主线程会为子线程阻塞,如果子线程没有执行完,那么主线程就永远不会执行phread_join()下面的程序。程序如下:
   

#include <stdio.h>
#include <pthread.h>

void pthread_1()
{
 printf("I am the child!!\n");
 
 sleep(2);
 
 printf("I am exit!!\n");
 
}

void main()
{
 pthread_t tid;
 void *tret;
 
 pthread_create(&tid, NULL, &pthread_1, NULL);
 pthread_join(tid, &tret);
 printf("Thread exit with code %d\n", (int)tret);
 exit(0);
}   

2)、主线程终止子线程
在posix   thread中线程有两中取消状态:立即取消和延迟取消
立即取消就是pthread_cancel之后,不管理线程在干什么,马上终止这个线程
而延迟取消是在pthread_cancel之后,线程会继续运行,直到遇到一个 "取消点函数 "
系统默认的是延迟取消

如果想要结束线程有几个方法
a.线程设置为立即取消
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,   NULL);  

程序如下

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>

void pthead_1()
{
 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,   NULL);  
 
 while(1)
 {
  printf("I am the child \n"); 
  usleep(10000);
 } 
 
}

void main()
{
 pthread_t pthread_id;
 
 pthread_create(&pthread_id, NULL, &pthead_1, NULL);
 
 sleep(2);
 
 pthread_cancel(pthread_id);
 
 printf("I make the child exit!!\n");
 pthread_exit(0);
 
}


b.在你的线程中加入一些取消点函数的调用
while(   1   )
{
//sleep(1)或者pthread_testcancle();
}

 
    5、 回收线程
    线程创建时,detachsate属性是PTHREAD_CREATE_DETACHED,则在开始函数返回后被回收。
或其他线程使用了pthread_join 或自己调用了pthread_detach,线程出于terminated状态后,立马就会被系统回收:释放系统资源和进程资源,包含线程返回值占用的内存,线程堆栈,寄存器状态等等。
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值