对进程线程的印象还是比较好的,这对于学习C高级的朋友是非常重要的,怎样更快的学习到线程的具体使用呢?最好的办法自然是练习再练习,然后还要看很多的代码才是,之前又听说了一个IT同行过劳死,特别的提醒广大的IT从业者,要注意合理的作息习惯,健康才是最重要的,下面结合网上的一些文章,对线程进行详细的剖析
一、线程的基本概念
进程(process)和文件(files)是unix/linux操作系统两个最基本的抽象。进程是处于执行期的程序和它所包含的资源的总和,也就是说一个进程就是处于执行期的程序。一个线程(thread)就是运行在一个进程上下文中的一个逻辑流,不难看出,线程是进程中最基本的活动对象。
在传统的系统中,一个进程只包含有一个线程。但在现代操作系统中,允许一个进程里面可以同时运行多个线程,这类程序就被称为多线程程序。所有的程序都有一个主线程(main thread),主线程是进程的控制流或执行线程。在多线程程序中,主线程可以创建一个或多个对等线程(peer thread),从这个时间点开始,这些线程就开始并发执行。主线程和对等线程的区别仅在于主线程总是进程中的第一个运行的线程。从某种程度上看,线程可以看作是轻量级的进程。在linux操作系统中,内核调度的基本对象时线程,而不是进程,所以进程中的多个线程将由内核自动调度。
每个线程都拥有独立的线程上下文(thread context),线程ID(thread ID,TID),程序计数器(pc),线程栈(stack)。其中,内核正是通过线程ID(TID)来识别线程,进行线程调度的。
二、线程与进程的异同点
A.相同点
<1> 比如都具有ID,一组寄存器,状态,优先级以及所要遵循的调度策略。
<2>每个进程都有一个进程控制块,线程也拥有一个线程控制块(在Linux内核,线程控制块与进程控制块用同一个结构体描述,即struct task_struct),这个控制块包含线程的一些属性信息,操作系统使用这些属性信息来描述线程。
<3>线程和子进程的创建者可以在线程和子进程上实行某些控制,比如,创建者可以取消、挂起、继续和修改线程和子进程的优先级。
B.不同点
<1>主要区别:每个进程都拥有自己的地址空间,但线程没有自己独立的地址空间,而是运行在一个进程里的所有线程共享该进程的整个虚拟地址空间。
<2>线程的上下文切换时间开销比进程上下文切换时间开销要小的多
<3>线程的创建开销远远小于进程的创建
<4>子进程拥有父进程的地址空间和数据段的拷贝,因此当子进程修改它的变量和数据时,它不会影响父进程中的数据,但线程可以直接访问它进程中的数据段。
<5>进程之间通讯必须使用进程间通讯机制,但线程可以与进程中的其他线程直接通讯
<6>线程可以对同一进程中的其他线程实施大量控制,但进程只能对子进程实施控制
<7>改变主线程的属性可能影响进程中其他的线程,但对父进程的修改不影响子进程
三、线程相关的API
A.线程的创建
参数说明:
thread:指向pthread_t类型的指针,该地址将存放线程创建成功之后的线程TID。
attr:用户设置线程的属性,一般都不需要特殊设置,所以可简单设置为NULL。
*(*start_routine)(void *):传递新线程所要执行的函数的地址。
arg:新线程所有执行的函数的参数。
调用成功,则返回值是0,如果失败则返回错误代码。
注意:我们可以看到,如果想启动一个线程,就必须让这个线程关联一个子函数。我们一般称此函数为线程函数,但是我们又发现,在我们给线程函数传参数时,标准线程创建接口只留了 一个参数传递。思考?如果想给线程函数传递多个参数,该怎么解决呢?
B.线程终止
参数说明 :
value_ptr指向线程放回的某个对象
线程通过调用pthread_exit函数终止执行,并带回指向某个对象的指针。
注意:绝不能用它返回一个指向局部变量的指针,因为线程调用该函数后,这个局部变量就不存在了,这将引起严重的程序漏洞。
C.等待线程终止
一般此函数用在主线程中,等待通过thread指定的线程终止,此函数调用成功,可以通过value_ptr获取终止线程的返回值。
注意:如果等待的线程没有终止,此函数将引起调用者阻塞。成功返回0,失败返回-1。
如果想取消一个正在运行的线程,可以调用此函数。
参数说明:
thread:要取消的线程
函数返回值:成功返回0,失败返回-1
案例探究:
- #include <stdio.h>
- #include <stdlib.h>
- #include <pthread.h>
- #include <string.h>
-
- char buf[] = "Hello word";
-
- void *pthread_function1(void *arg)
- {
- while(1)
- {
- sleep(2);
- printf("pthread_function : %s.\n",buf);
- }
- }
-
- void *pthread_function2(void *arg)
- {
- int i = 0;
-
- for(i = 0;i < strlen(buf);i ++)
- {
- *(int *)arg += 1;
- sleep(1);
- }
-
- pthread_exit("pthread_function2 over");
- }
-
- int main()
- {
- pthread_t tid1,tid2;
- int count = 0;
- void *value_ptr;
-
- if(pthread_create(&tid1,NULL,pthread_function1,NULL) != 0)
- {
- perror("Fail to pthread create");
- return -1;
- }else{
- printf("create pthread %lu.\n",tid1);
- }
-
- if(pthread_create(&tid2,NULL,pthread_function2,(void *)&count) != 0)
- {
- perror("Fail to pthread create");
- exit(EXIT_FAILURE);
- }else{
- printf("create pthread %lu.\n",tid2);
- }
-
- if(pthread_join