多线程的使用
典型的线程包括一个运行时间系统,它可以按透明的方式来管理线程。通常线程包包括对线程的创建和删除,以及对互斥和条件变量的调用。POSIX标准线程库具有这些调用。这些包还提供线程的动态创建和删除,因此,直到运行时间之前,线程的个数不必知道。
线程具有一个ID、一个堆栈、一个执行优先权,以及执行的开始地址。POSIX线程通过pthread_t类型的ID来引用。pthread_t其实就是无符号长整型,在文件/usr/include/bits/pthreadtypes.h有如下定义:
typedef unsigned long int pthread_t;
线程的内部数据结构也包含调度和使用信息。进程的线程共享进程的完整地址空间,它们能够修改全局变量,访问打开的文件描述符,或用别的方式相互作用。
1、 pthread_create函数
如果线程可在进程的执行期间的任意时刻被创建,并且线程的数量事先没有必要指定,这样的线程称为动态线程。在POSIX中,线程是用pthread_create动态的创建的。pthread_create能创建线程,并将它放入就绪队列。创建线程需要调用pthread_create,该函数的定义如下所示:
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void*(*start_routine)(void *),void *arg);
该函数的第1个参数thread将指向创建线程的ID。线程的属性是由attr指向的属性对象来包容的。如果attr为NULL,新线程具有缺省的属性。第3个参数start_routine是线程开始执行时调用的函数名字。start_routine占用一个参数arg,它是一个指向viod的指针。start_routine返回一个指向viod的指针,此指针被空作时pthread_jion的退出状态。
函数pthread_create在成功调用时返回0,失败时返回-1。
2、 pthread_self函数
在创建线程之后,可以调用pthread_self得到线程的ID,该函数的定义如下所示:
#include <pthread.h>
pthread_t pthread_self(void);
3、 pthread_exit函数
与进程退出时调用exit类似,线程退出时也需要调用pthread_exit,它的定义如下:
#include <pthread.h>
void pthread_exit(void* retval);
函数pthread_exit终止调用的线程。参数retval的值对pthread_join函数的成功由实际意义。然而,pthread_exit的retval必须指定,在线程退出时它才退出的数据,因此它不能够作为正在退出的线程的自动局部数据被分配。
函数pthread_exit在成功调用时返回0,失败时返回-1。
4、 pthread_join函数
在成功创建线程之后,可以调用pthread_join将创建的线程加入到原进程中去,pthread_join的定义如下所示:
#include <pthread.h>
int pthread_join(pthread_t th,void **thread_return);
如果调用了pthread_join,那么进程会等待线程调用pthread_exit之后才退出,这个函数的作用类似于wait系统调用。pthread_join的第1个参数th为所创建线程的ID,第2个参数指向线程的退出码。
函数pthread_join在成功调用时返回0,失败时返回-1。
5、例子
#include <iostream>
#include <pthread>
using namespace std;
void *thread(void *arg)
{
printf("new thread!");
return 0;
}
int main()
{
pthread_t ntid;
int err;
err = pthread_create(&ntid,NULL,thread,NULL);
if(err !=0)
{
printf("can't create thread: %s/n",strerror(err));
}
printf("man thread/n");
sleep(1);
return 0;
}
这个例子的编译运行如下:
而对于用arm-linux-gcc编译的时候后面需要加上-lpthread
参考:毛曙福 《linux C高级程序员指南》国防工业出版社
多线程互斥方法
在使用互斥变量之前需要定义互斥变量:
pthread_mutex_t mutex;
然后对变量进行初始化,也即向内核申请互斥变量
pthread_mutex_init(&mutex, NULL);
进入临界区之前需要对变量进行加锁:
pthread_mutex_lock(&mutex);
……………………
最后退出临界区的时候需要进行解锁
pthread_mutex_unlock(&mutex);