线程创建与等待
一.概述:
首先谈一下为什么要有线程。众所周知,一个进程只能进行一个执行流,虽然能创建子进程,但创建,终止,切换进程和进程间的通信的开销比较大,所以现代操作系统一般都使用线程。
现在再谈一下我所了解的线程功能。一般可以这样认为,进程负责的是分配资源,而线程负责的是调度和执行。线程又叫轻量级进程。而传统的进程即负责分配资源,又承担一个线程的执行。
进程和线程的区别:除了上面功能与性能的不同,还可以从进程管理的角度来区别。在单线程模型中,进程的表示包括它的进程控制块,用户地址空间,以及进程执行中管理调用/返回行为的用户栈,内核栈。在多线程环境中,进程只有一个与之关联的进程控制块和用户地址空间,而线程都有一个独立的栈,还有独立的控制块(包括寄存器,优先级和其它与线程相关的状态信息)。如下图:(摘自操作系统精髓与设计原理第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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
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 }
|
执行结果: