一、线程的一般概念
线程可以看作是轻量级的进程,所有的程序都有一个主线程(main thread),主线程是进程的控制流或执行线程。在多线程程序中,主线程可以创建一个或多个对等线程(peer thread),从这个时间点开始,这些线程就开始并发执行。主线程和对等线程的区别仅在于主线程总是进程中第一个运行的线程。线程有两个优点:资源消耗量少和方便的通信机制。
二、线程的常用操作
(1)创建一个线程:pthread_create
int pthread_create(pthread_t *thread,pthread_attr_t *attr,void *(*start_routine)(void*),void *arg);
第一个参数为要创建的线程结构pthread_t,第二个参数为线程的相关属性,第三个参数是该线程要执行的函数的指针,第四个则是传递给*start_routine的参数,可以自行选择它的取值和用法。
pthread_create执行成功返回0,并把tid线程标识符存放到pthread_t结构中;否则返回一个非零值并设置errno。
(2)终止当前线程:pthread_exit
void pthread_exit(void *retval);
pthread_exit退出当前线程,退出之前将调用pthread_cleanup_push。它在线程的最上层函数的最后是被隐式调用的,这时可以 加一个retval参数显式调用之,以供pthread_join参考。
(3)挂起当前线程:pthread_join
int pthread_join(pthread_t th,void **thread_return);
pthread_join把当前线程挂起直到指定的线程th终止,thread_return为th终止时的参数,如果没有显式指定,则为NULL。
(4)撤消一个线程:pthread_cancel
int pthread_cancel(pthread_t thread);
(5)等待线程的结束:pthread_join
int pthread_join(pthread_t th,void **thread_return);
调用这个函数的线程会挂起,直到等待的线程结束。这个函数的主要目的就是等待指定的线程结束,回收其内存资源。否则会浪费大量的内存资源。
三、线程资源互锁
由于线程是共享资源的,所以互斥就显得相当重要。互斥提供了对互斥对象上锁的方法以获得对此资源的独占,其它企图对此互斥加锁的线程则会被阻塞而挂起,直到对资源加锁的线程解锁为止。
在使用线程编程时,不必处处都使用互斥,否则会失去并发线程的意义,例如,在对使用只能串行单独访问的资源下方使用互斥。
互斥对象在pthead.h中定义为pthread_mutex_t。它的系统调用主要包括:
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutex_attr_t *mutexattr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
pthread_mutex_init创建一个互斥对象,并用指定的属性初始化这个互斥对象,初始化属性包 括:PTHREAD_MUTEX_INITIALIZER创建快速互斥,这种互斥执行简单的加锁和解锁,在加锁后阻塞另一个要给它上锁的线 程;PTHREAD_RECURSIVE_MUTEX_INITIALIZER创建递归互斥,这种互斥将给加锁计数,解锁时需要调用同样次数的 pthread_mutex_unlock;
PTHREAD_ERRORCHECK_MUTEX_INITIALIZER创建检错互斥,这种互斥在被锁上后会向试图给它加锁的线程返回一个EDEADLK错误代码而不阻塞。
pthread_mutex_lock和pthread_mutex_unlock则为加锁和解锁指定的互斥对 象,pthread_mutex_trylock和pthread_mutex_lock的不同是如果互斥对象已上锁不会被阻塞而是返回一个EBUSY错 误代码,pthread_mutex_destory析构指针mutex并释放相关资源。这几个调用成功都返回0,失败返回一个非零的错误代码。
四、线程的维护
当创建完一个线程后,线程会根据CPU的时间分配就开始执行线程中的内容,为了线程能够稳定的运行,即防止CPU阻塞等其他原因造成线程得不到CPU,而使得线程无法执行。这里采用当运行到一定时间内,如果线程得不到执行,则撤销先前的线程,重新建立。其一般操作如下:
(1)设置一个全局变量 g_SocketErr ;
(2)在线程中除了运行你要的功能以外,将 g_SocketErr=0;
(3)在main函数的while(1)中,
if (g_SocketErr>= 10) //若10次检测都不正常,则关闭此线程,然后重新打开此线程 { nErr = pthread_cancel(sock_tid); if (nErr != 0) { printf("cancel pthread_ipc error!\n"); } else { pthread_join(sock_tid, NULL); nErr = pthread_create(&sock_tid, NULL, ThreadSocket, NULL); //打开环回socket线程 if (nErr != 0) { printf("creat socket err"); } else { g_SocketErr = 0; printf("Thread pthread_ipc create OK!\n"); } } } else { g_SocketErr++; }
好了,这次就总结到这里。
参考:POSIX线程基本概念
http://blog.chinaunix.net/uid-14846899-id-2782352.html 这位同学整理的多线程读书笔记整理的不错。可以重点看下。
http://fanqiang.chinaunix.net/a4/b8/20010811/0905001105.html