[摘至linux C编程实战]
线程控制
1.线程与进程的关系
线程是计算机中独立运行的最小单位,运行时占用很少的系统资源。可以把线程看成是操作系统分配CPU时间的基本单元。一个进程可以拥有一个至多个线程。它包含有如下优点:
1)多进程情况下,每个进程有自己独立的地址空间,而在多线程的情况下,同一个进程内的线程共享进程的地址空间。创建一个新的线程耗费的资源要少很多。
2)系统调度方面,线程共享地址空间,因此线程间的切换速度要远远快于进程间的切换速度。
3)同一进程内的线程共享数据时,可以直接提供给其他线程使用,而不必经过操作系统,因此线程间通信更加方便和省时。
线程在进程内部共享地址空间、打开的文件描述符等资源。同时线程也有其私有的数据信息,包括:线程号、寄存器(程序计数器和堆栈指针)、堆栈、信号掩码、优先级、线程私有存储空间。
2.创建线程
linux系统支持POSIX多线程接口,称为pthread。编写linux下的多线程程序,需要包含头文件pthread.h,链接时需要使用库libpthread.a
如果在主线程里面创建线程,程序就会在创建线程的地方产生分支,变成两个部分执行。线程的创建通过函数pthread_create来完成。成功返回0
int pthread_create(pthread_t *thread, pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg);
thread: 参数是一个指针,当线程成功创建时,返回创建线程ID。
attr: 用于指定线程的属性
start_routine: 该参数是一个函数指针,指向线程创建后要调用的函数。
arg: 传递给线程函数的参数。
例子:
1
#include
<
stdio.h
>
2
#include
<
stdlib.h
>
3
#include
<
unistd.h
>
4
#include
<
pthread.h
>
5
6
int
*
thread(
void
*
arg)
7
{8 pthread_t newthid;9 newthid=pthread_self();10 printf("this is a new thread, thread ID=%u\n", newthid);11returnNULL;12}
13
14
int
main(
void
)
15
{16 pthread_t thid;17 printf("main thread, ID is %u\n", pthread_self());18if(pthread_create(&thid, NULL, (void*)thread, NULL)!=0)19
{20 printf("thread creation failed\n");21 exit(1);22 }23 sleep(1);24 exit(0);25}
3.线程终止
两种方式终止线程。第一通过return从线程函数返回,第二种通过调用pthread_exit()函数使线程退出。需要注意的地方:一是,主线程中如果从main函数返回或是调用了exit函数退出主线程,则整个进程终止,此时所有的其他线程也将终止。另一种是,如果主线程调用pthread_exit函数,则仅仅是主线程消亡,进程不会结束,其他线程也不会结束,知道所有的线程都结束时,进程才结束。
4.线程私有数据
进程内的所有线程共享进程的数据空间,因此全局变量为所有线程所共有。但有时线程也需要保存自己的私有数据,这时可以创建线程私有数据(Thread-specific Date)TSD来解决。在线程内部,私有数据可以被各个函数访问,但对其他线程是屏蔽的。
线程私有数据采用了一键多值的技术,即一个键对应多个数值,访问数据时好像是对同一个变量进行访问,但其实是在访问不同的数据。
创建私有数据的函数有4个:pthread_key_create(创建), pthread_setspecific(设置), pthread_getspecific(获取), pthread_key_delete(删除)。
5.线程同步
线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点。linux下提供了多种方式来处理线程同步,最常用的是互斥锁、条件变量和异步信号。
1)互斥锁(mutex)通过锁机制实现线程间的同步。同一时刻只允许一个线程执行一个关键部分的代码。
2)条件变量(cond)是利用线程间共享的全局变量进行同步的一种机制。
3)异步信号,如同进程一样,线程也可以通过信号量来实现通信,虽然是轻量级的。