现在的位置: 首页 > 综合 > 正文

old《APUE 2e》学习笔记 Chapter 11. Threads

2014年02月17日 ⁄ 综合 ⁄ 共 8648字 ⁄ 字号 评论关闭

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将包含它的退出代码,如果该线程被canceledrval_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>

抱歉!评论已关闭.