第11章
Threads
1.线程的简单函数:
线程 ID类型:pthread_t
比较两个线程ID:
#include <pthread.h>
int pthread_equal(pthread_t tid1, pthread_t tid2);
Returns: nonzero if equal, 0 otherwise
返回自己的线程ID:
#include <pthread.h>
pthread_t pthread_self(void);
Returns: the thread ID of the calling thread
2.创造线程
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr,
void *(*start_rtn)(void), void *restrict arg);
Returns: 0 if OK, error number on failure
3.线程终止:
1)If any thread within a process calls
exit, _Exit, or _exit, then the entire process terminates.
2)
A single thread can exit in three ways, thereby stopping its flow of control, without terminating
the entire process.
* The thread can simply return from the start routine. The return value is the thread's exit code.
* The thread can be canceled by another thread in the same process.
* The thread can call pthread_exit.
终止调用的线程:
#include <pthread.h>
void pthread_exit(void *rval_ptr);
注意:如果rval_ptr是结构体,要用全局变量或者动态分配内存。
等待另一线程的结束:
#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
Returns: 0 if OK, error number on failure
作用:*
调用线程将阻塞,直到指定线程调用pthread_exit()或者返回到它的开始例程。如果是简单的返回,
rval_ptr将包含它的退出代码,如果该线程被canceled,rval_ptr将设置为PTHREAD_CANCELED.
* 将被指定的线程设置为分离状态,所以它的资源可以被恢复。如果该线程已经处于分离状态,pthread_join将失败,returning EINVAL
一个线程请求结束同一进程里的另一个线程:
#include <pthread.h>
int pthread_cancel(pthread_t tid);
Returns: 0 if OK, error number on failure
4.线程在退出时可以安排执行一些清理函数:
#include <pthread.h>
void pthread_cleanup_push(void (*rtn)(void *),void *arg);
void pthread_cleanup_pop(int execute);
执行清理函数,必须满足下列条件之一:
* Makes a call to pthread_exit
* Responds to a cancellation request
* Makes a call to pthread_cleanup_pop with a nonzero execute argument
****************************
例子 11.1
***************************************
举例说明在线程调用清理函数的例程
********************************************************************************
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
void
cleanup(void *arg)
{
printf("cleanup: %s/n",(char *)arg);
}
void *
thr_fn1(void *arg)
//退出时没有调用清理线程
{
printf("thread 1 start/n");
pthread_cleanup_push(cleanup,"thread 1 first handler");
pthread_cleanup_push(cleanup,"thread 1 second handler");
printf("thread 1 push complete/n");
if(arg)
return ((void * )1);
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
return ((void *)1);
}
void *
thr_fn2(void *arg)
// Makes a call to pthread_exit
{
printf("thread 2 start/n");
pthread_cleanup_push(cleanup,"thread 2 first handler");
pthread_cleanup_push(cleanup,"thread 2 second handler");
printf("thread 2 push complete/n");
if(arg)
pthread_exit((void *)2);
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
pthread_exit((void *)2);
}
void *
thr_fn3(void *arg)
// Makes a call to pthread_cleanup_pop with a nonzero execute argument
{
printf("thread 3 start/n");
pthread_cleanup_push(cleanup,"thread 3 first handler");
pthread_cleanup_push(cleanup,"thread 3 second handler");
printf("thread 3 push complete/n");
pthread_cleanup_pop(1);
pthread_cleanup_pop(1);
return 0;
}
void *
thr_fn4(void *arg)
// Responds to a cancellation request
{
printf("thread 4 start/n");
pthread_cleanup_push(cleanup,"thread 4 first handler");
pthread_cleanup_push(cleanup,"thread 4 second handler");
printf("thread 4 push complete/n");
sleep(2);
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
return 0;
}
int main()
{
int err;
pthread_t tid1,tid2,tid3,tid4;
void *tret;
err=pthread_create(&tid1,NULL,thr_fn1,(void *)1);
if(err!=0)
printf("can't create thread 1:%s/n",strerror(err));
err=pthread_create(&tid2,NULL,thr_fn2,(void *)1);
if(err!=0)
printf("can't create thread 2:%s/n",strerror(err));
err=pthread_create(&tid3,NULL,thr_fn3,(void *)1);
if(err!=0)
printf("can't create thread 3:%s/n",strerror(err));
err=pthread_create(&tid4,NULL,thr_fn4,(void *)1);
if(err!=0)
printf("can't create thread 4:%s/n",strerror(err));
err=pthread_cancel(tid4);
if(err!=0)
printf("can't cancel with thread 4: %s/n",strerror(err));
err=pthread_join(tid1,&tret);
if(err!=0)
printf("can't join with thread 1: %s/n",strerror(err));
printf("thread 1 exit code %d/n",(int)tret);
err=pthread_join(tid2,&tret);
if(err!=0)
printf("can't join with thread 2:%s/n",strerror(err));
printf("thread 2 exit code %d/n",(int)tret);
err=pthread_join(tid3,&tret);
if(err!=0)
printf("can't join with thread 3:%s/n",strerror(err));
printf("thread 3 exit code %d/n",(int)tret);
err=pthread_join(tid4,&tret);
if(err!=0)
printf("can't join with thread 4:%s/n",strerror(err));
printf("thread 4 exit code %d/n",(int)tret);
exit(0);
}
结果:
thread 1 start
thread 1 push complete
thread 2 start
thread 2 push complete
cleanup: thread 2 second handler
cleanup: thread 2 first handler
thread 3 start
thread 3 push complete
cleanup: thread 3 second handler
cleanup: thread 3 first handler
thread 4 start
thread 4 push complete
thread 1 exit code 1
thread 2 exit code 2
thread 3 exit code 0
cleanup: thread 4 second handler
cleanup: thread 4 first handler
thread 4 exit code -1
*********************************************************************************************
5.
By default, a thread's termination status is retained until pthread_join is called for that thread. A thread's underlying storage can be reclaimed immediately on termination if that thread has been detached.
When a thread is detached, the pthread_join function can't be used to wait for its termination status. A call to pthread_join for a detached thread will fail, returning EINVAL. We can detach a thread by calling pthread_detach.
使线程处于分离状态
#include <pthread.h>
int pthread_detach(pthread_t tid);
Returns: 0 if OK, error number on failure
6.
比较线程和进程的函数
Process |
Thread |
Description |
fork |
pthread_create |
create a new flow of control |
exit |
pthread_exit |
exit from an existing flow of control |
waitpid |
pthread_join |
get exit status from flow of control |
atexit |
pthread_cancel_push |
register function to be called at exit from flow of control |
getpid |
pthread_self |
get ID for flow of control |
abort |
pthread_cancel |
request abnormal termination of flow of control |
7.互斥锁:
互斥锁定义:pthread_mutex_t
互斥锁初始化: PTHREAD_MUTEX_INITIALIZER
注:仅使用于静态分配的互斥锁
或者以下面方式初始化,但要使用相应的注销函数:
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
Both return: 0 if OK, error number on failure
*****************************
例子 11.2 *************************************
线程的互斥锁的使用例程
*****************************************************************************
#include <stdio.h>
#include <pthread.h>
#include <string.h>
pthread_mutex_t flock;
char buf[512];
void *
thr_fn1(void *arg)
{
long i;
for(i=0;i<2000000;i++)
{
pthread_mutex_lock(&flock);
strcpy(buf,"aaaaaaaaaaaaaaaaaaaa/n");
strcpy(buf,"bbbbbbbbbbbbbbbbbbbb/n");
strcpy(buf,"cccccccccccccccccccc/n");
strcpy(buf,"dddddddddddddddddddd/n");
pthread_mutex_unlock(&flock);
}
}
void *
thr_fn2(void *arg)
{
int i;
for(i=0;i<10;i++)
{
pthread_mutex_lock(&flock);
printf(buf);
pthread_mutex_unlock(&flock);
usleep(5);
}
}
int main()
{
pthread_t tid1,tid2;
int err;
strcpy(buf,"hello,world!/n");
pthread_mutex_init(&flock,NULL);
err=pthread_create(&tid1,NULL,thr_fn1,NULL);
if(err!=0)
printf("can't create thread 1:%s/n",strerror(err));
err=pthread_create(&tid2,NULL,thr_fn2,NULL);
if(err!=0)
printf("can't create thread 1:%s/n",strerror(err));
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_mutex_destroy(&flock);
return 0;
}
*****************************************************************************
8.
读写锁:
定义:pthread_rwlock_t
初始化,销毁:
#include <pthread.h>
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
Both return: 0 if OK, error number on failure
执行互斥锁:
include <pthread.h>
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
All return: 0 if OK, error number on failure
9.条件变量
When used with mutexes, condition variables allow threads to wait in a race-free way for arbitrary conditions to occur.
The condition itself is protected by a mutex. A thread must first lock the mutex to change the condition state. Other threads will not notice the change until they acquire the mutex.
定义:
pthread_cond_t
初始化:PTHREAD_COND_INITIALIZER
//只限于使用在静态分配条件变量
pthread_cond_init()
但要调用
pthread_mutex_destroy 释放
#include <pthread.h>