一.概述:
首先谈一下为什么要有线程。众所周知,一个进程只能进行一个执行流,虽然能创建子进程,但创建,终止,切换进程和进程间的通信的开销比较大,所以现代操作系统一般都使用线程。
现在再谈一下我所了解的线程功能。一般可以这样认为,进程负责的是分配资源,而线程负责的是调度和执行。线程又叫轻量级进程。而传统的进程即负责分配资源,又承担一个线程的执行。
进程和线程的区别:除了上面功能与性能的不同,还可以从进程管理的角度来区别。在单线程模型中,进程的表示包括它的进程控制块,用户地址空间,以及进程执行中管理调用/返回行为的用户栈,内核栈。在多线程环境中,进程只有一个与之关联的进程控制块和用户地址空间,而线程都有一个独立的栈,还有独立的控制块(包括寄存器,优先级和其它与线程相关的状态信息)。如下图:(摘自操作系统精髓与设计原理第4章)
注:如果在多处理器机器上,多线程的性能会更优。
二.相关函数:(PS:这里的线程库函数是由POSIX标准定义的,称为POSIX thread或者pthread。)
pthread_create: int pthread_create(pthread_t *pthread, const pthread_attr_t *attr,
void *(*start_toutine)(void *), void *arg)
函数功能:创建一个线程,使线程从传入的函数指针所指的函数中开始执行。
pthread参数:输出型参数,创建成功会把线程id放入里面。
attr参数:用来设置线程的属性,如线程的分离状态属性,线程栈的大小等。一般为NULL就可以了。
start_toutine参数:函数指针,用于指明线程从哪里开始执行。
arg参数:传入函数指针所指的函数的参数。
返回值:所有pthread函数都是成功返回0,失败返回一个错误号。可以用strerror显示错误号。
PS:主线程会从函数返回出继续往下执行。
2.pthread_exit:void pthread_exit(void *retval)
函数功能:线程可以调用自己进行注销操作。
retval参数:退出时返回的值。
3.pthread_cancel:int pthread_cancel(pthread_t pthread)
函数功能:注销线程id为pthread的线程。
返回值:成功返回0,失败返回一个错误号。
4.pthread_join:int pthread_join(pthread_t pthread, void** retval)
函数功能:将线程id为pthread的线程挂起等待,直到线程终止,终止状态保持到retval中。
retval参数:输出型参数,用于保存线程终止的终止状态。不同的终止方法有不同的终止状态:
(1).如果线程通过return返回,retval中指向的单元里存放的是线程函数的返回值。
(2).如果线程被别的线程调用pthread_cancel异常终止,retval指向的单元中存放的是常数PTHREAD_CALCELED。
(3).如果线程自己调用pthread_exit()函数终止的,retval指向的单元中存放的是传给pthead_exit()的参数。
返回值:成功返回0,失败返回一个错误号。
三.相关代码:(PS:编译时要加 -Lpthread)
创建一个进程:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<pthread.h>
4
5 pthread_t tid;
6
7 void* create_thread(void *ptr)
8 {
9 printf("%s . pid is:%d tid is:%ul \n",(char *)ptr, (int)getpid(), (unsigned long long)pthread_self());
10 return NULL;
11 }
12
13 int main()
14 {
15 int err = pthread_create(&tid, NULL, create_thread, "i'm a thread");
16 if(err != 0)
17 {
18 printf("create thread failed! info is :%s", strerror(err));
19 exit(err);
20 }
21
22 printf("main thread run. pid is:%d tid is:%ul \n", (int)getpid(), (unsigned long long)pthread_self());//linux 下tid为一个地址值
23 sleep(1);
24 return 0;
25 }
执行结果:
2.线程等待:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<pthread.h>
4
5 void *create_thread1(void *ptr)
6 {
7 printf("this is thread1\n");
8 return (void *)1;
9 }
10
11 void *create_thread2(void *ptr)
12 {
13 printf("this is thread2\n");
14 pthread_exit((void *)2);
15 }
16
17 void *create_thread3(void *ptr)
18 {
19 while(1)
20 {
21 printf("this is thread3,waiting for be calceled.....\n");
22 sleep(1);
23 }
24 return NULL;
25 }
26
27 int main()
28 {
29 pthread_t tid;
30 void* ret;
31
32 int err1 = pthread_create(&tid, NULL, create_thread1, NULL);
33 if(err1 != 0)
34 {
35 printf("create thread failed!");
36 }
37 pthread_join(tid, &ret);
38 printf("thread is returned,tid is:%ul return code is:%d \n", (unsigned long long)pthread_self(), (int)ret);
39
40 int err2 = pthread_create(&tid, NULL, create_thread2, NULL);
41 if(err2 != 0)
42 {
43 printf("create thread failed!");
44 }
45 pthread_join(tid, &ret);
46 printf("thread is exited,tid is:%ul return code is:%d \n", (unsigned long long)pthread_self(), (int)ret);
47
48 int err3 = pthread_create(&tid, NULL, create_thread3, NULL);
49 if(err3 != 0)
50 {
51 printf("create thread failed!");
52 }
53 sleep(3);
54 pthread_cancel(tid);
55 pthread_join(tid, &ret);
56 printf("thread is canceled,tid is:%ul return code is:%d \n", (unsigned long long)pthread_self(), (int)ret);
57
58 return 0;
59 }
执行结果:
转载于:https://blog.51cto.com/10704527/1765574