APUE 线程 - 程序清单

来源:互联网 发布:java开发实战经典下载 编辑:程序博客网 时间:2024/05/21 17:57
APUE 线程 - 程序清单


程序清单11-1 打印线程ID
#include "util.h"#include<pthread.h>pthread_t ntid;voidprintids(const char *s){pid_tpid;pthread_ttid;pid = getpid();tid = pthread_self();//之所以打印16进制,便于pthread_t是结构体的话看地址;printf("%s pid %u tid %u (0x%x)\n", s, (unsigned int)pid,  (unsigned int)tid, (unsigned int)tid);}void *thr_fn(void *arg){printids("new thread: ");return((void *)0);}intmain(void){interr;err = pthread_create(&ntid, NULL, thr_fn, NULL);if (err != 0)err_quit("can't create thread: %s\n", strerror(err));printids("main thread:");sleep(1);//确保会执行新线程exit(0);}



程序清单11-2  获得线程退出状态
#include "util.h"#include <pthread.h>void *thr_fn1(void *arg){printf("thread 1 returning\n");return((void *)1);}void *thr_fn2(void *arg){printf("thread 2 exiting\n");pthread_exit((void *)2);}intmain(void){interr;pthread_ttid1, tid2;void*tret;err = pthread_create(&tid1, NULL, thr_fn1, NULL);if (err != 0)err_quit("can't create thread 1: %s\n", strerror(err));err = pthread_create(&tid2, NULL, thr_fn2, NULL);if (err != 0)err_quit("can't create thread 2: %s\n", strerror(err));err = pthread_join(tid1, &tret);if (err != 0)err_quit("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)err_quit("can't join with thread 2: %s\n", strerror(err));printf("thread 2 exit code %d\n", (int)tret);exit(0);}



程序清单11-3  pthread_exit 的参数不正确使用
#include "util.h"#include <pthread.h>struct foo {int a, b, c, d;};voidprintfoo(const char *s, const struct foo *fp){printf(s);printf("  structure at 0x%x\n", (unsigned)fp);printf("  foo.a = %d\n", fp->a);printf("  foo.b = %d\n", fp->b);printf("  foo.c = %d\n", fp->c);printf("  foo.d = %d\n", fp->d);}void *thr_fn1(void *arg){struct foofoo = {1, 2, 3, 4};printfoo("thread 1:\n", &foo);pthread_exit((void *)&foo);//这里是自动变量,退出的时候只是告知监听者退出状态码所在的地址,但是里面的内容在函数退出时就变了;}void *thr_fn2(void *arg){printf("thread 2: ID is %ld\n", pthread_self());//这里最好用长整型;pthread_exit((void *)0);}intmain(void){interr;pthread_ttid1, tid2;struct foo*fp;err = pthread_create(&tid1, NULL, thr_fn1, NULL);if (err != 0)err_quit("can't create thread 1: %s\n", strerror(err));err = pthread_join(tid1, (void *)&fp);if (err != 0)err_quit("can't join with thread 1: %s\n", strerror(err));sleep(1);printf("parent starting second thread\n");err = pthread_create(&tid2, NULL, thr_fn2, NULL);if (err != 0)err_quit("can't create thread 2: %s\n", strerror(err));sleep(1);printfoo("parent:\n", fp);exit(0);}



程序清单11-4  线程清理处理程序
#include "util.h"#include <pthread.h>voidcleanup(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){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);}intmain(void){interr;pthread_ttid1, tid2;void*tret;err = pthread_create(&tid1, NULL, thr_fn1, (void *)1);if (err != 0)err_quit("can't create thread 1: %s\n", strerror(err));err = pthread_create(&tid2, NULL, thr_fn2, (void *)1);if (err != 0)err_quit("can't create thread 2: %s\n", strerror(err));err = pthread_join(tid1, &tret);if (err != 0)err_quit("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)err_quit("can't join with thread 2: %s\n", strerror(err));printf("thread 2 exit code %d\n", (int)tret);exit(0);}



程序清单11-5  使用互斥量保护数据结构
#include <stdlib.h>#include <stdio.h>#include <pthread.h>struct foo {int             f_count;pthread_mutex_t f_lock;/* ... more stuff here ... */};struct foo *foo_alloc(void) /* allocate the object */{struct foo *fp;if ((fp = malloc(sizeof(struct foo))) != NULL) {fp->f_count = 1;if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {free(fp);return(NULL);}/* ... continue initialization ... */}return(fp);}voidfoo_hold(struct foo *fp) /* add a reference to the object */{pthread_mutex_lock(&fp->f_lock);fp->f_count++;pthread_mutex_unlock(&fp->f_lock);}voidfoo_rele(struct foo *fp) /* release a reference to the object */{pthread_mutex_lock(&fp->f_lock);if (--fp->f_count == 0) { /* last reference */pthread_mutex_unlock(&fp->f_lock);pthread_mutex_destroy(&fp->f_lock);free(fp);} else {pthread_mutex_unlock(&fp->f_lock);}}void *thr_fn1(void *pp){struct foo *p=(struct foo *)pp;printf("thread 1.......\n");foo_hold(p);pthread_exit((void*)1);}void *thr_fn2(void *pp){struct foo *p=(struct foo *)pp;        printf("thread 2.......\n");        foo_hold(p);        pthread_exit((void*)2);}int main(){pthread_t tid1,tid2;void * ret1,*ret2;struct foo *pf;pf = foo_alloc();if(!pf)exit(-1);pthread_create(&tid1,NULL,thr_fn1,(void *)pf);pthread_join(tid1,&ret1);printf("main 1 : %d --\n",pf->f_count);pthread_create(&tid2,NULL,thr_fn2,(void *)pf);printf("main 2 : %d --\n",pf->f_count);pthread_join(tid2,&ret2);printf("main 3 : %d --\n",pf->f_count);}


程序清单11-6  使用两个互斥量
#include <stdlib.h>#include <pthread.h>#define NHASH 29#define HASH(fp) (((unsigned long)fp)%NHASH)struct foo *fh[NHASH];pthread_mutex_t hashlock = PTHREAD_MUTEX_INITIALIZER;struct foo {int             f_count;pthread_mutex_t f_lock;struct foo     *f_next; /* protected by hashlock */int             f_id;/* ... more stuff here ... */};struct foo *foo_alloc(void) /* allocate the object */{struct foo*fp;intidx;if ((fp = malloc(sizeof(struct foo))) != NULL) {fp->f_count = 1;if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {free(fp);return(NULL);}idx = HASH(fp);pthread_mutex_lock(&hashlock);fp->f_next = fh[idx];fh[idx] = fp->f_next;pthread_mutex_lock(&fp->f_lock);pthread_mutex_unlock(&hashlock);/* ... continue initialization ... */thread_mutex_unlock(&fp->f_lock);}return(fp);}voidfoo_hold(struct foo *fp) /* add a reference to the object */{pthread_mutex_lock(&fp->f_lock);fp->f_count++;pthread_mutex_unlock(&fp->f_lock);}struct foo *foo_find(int id) /* find an existing object */{struct foo*fp;intidx;idx = HASH(fp);pthread_mutex_lock(&hashlock);for (fp = fh[idx]; fp != NULL; fp = fp->f_next) {if (fp->f_id == id) {foo_hold(fp);break;}}pthread_mutex_unlock(&hashlock);return(fp);}voidfoo_rele(struct foo *fp) /* release a reference to the object */{struct foo*tfp;intidx;pthread_mutex_lock(&fp->f_lock);if (fp->f_count == 1) { /* last reference */pthread_mutex_unlock(&fp->f_lock);pthread_mutex_lock(&hashlock);pthread_mutex_lock(&fp->f_lock);/* need to recheck the condition */if (fp->f_count != 1) {fp->f_count--;pthread_mutex_unlock(&fp->f_lock);pthread_mutex_unlock(&hashlock);return;}/* remove from list */idx = HASH(fp);tfp = fh[idx];if (tfp == fp) {fh[idx] = fp->f_next;} else {while (tfp->f_next != fp)tfp = tfp->f_next;tfp->f_next = fp->f_next;}pthread_mutex_unlock(&hashlock);pthread_mutex_unlock(&fp->f_lock);pthread_mutex_destroy(&fp->f_lock);free(fp);} else {fp->f_count--;pthread_mutex_unlock(&fp->f_lock);}}



程序清单11-7  简化的加,解锁
#include <stdlib.h>#include <pthread.h>#define NHASH 29#define HASH(fp) (((unsigned long)fp)%NHASH)struct foo *fh[NHASH];pthread_mutex_t hashlock = PTHREAD_MUTEX_INITIALIZER;struct foo {  int f_count;                  /* protected by hashlock */  pthread_mutex_t f_lock;  struct foo *f_next;           /* protected by hashlock */  int f_id;  /* ... more stuff here ... */};struct foo *foo_alloc(void)                 /* allocate the object */{  struct foo *fp;  int idx;  if ((fp = malloc(sizeof(struct foo))) != NULL) {    fp->f_count = 1;    if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {      free(fp);      return NULL;    }    idx = HASH(fp);    pthread_mutex_lock(&hashlock);    fp->f_next = fh[idx];    fh[idx] = fp;    pthread_mutex_lock(&fp->f_lock); // Why ???    pthread_mutex_unlock(&hashlock);    /* ... continue initialization ... */  }  return fp;}voidfoo_hold(struct foo *fp)        /* add a reference to the object */{  pthread_mutex_lock(&hashlock);  fp->f_count++;  pthread_mutex_unlock(&hashlock);}struct foo *foo_find(int id)                /* find an existing object */{  struct foo *fp;  int idx;  idx = HASH(fp);  pthread_mutex_lock(&hashlock);  for (fp = fh[idx]; fp != NULL; fp = fp->f_next) {    if (fp->f_id == id) {      fp->f_count++;      break;    }  }  pthread_mutex_unlock(&hashlock);  return fp;}voidfoo_rele(struct foo *fp)        /* release a reference to the object */{  struct foo *tfp;  int idx;  pthread_mutex_lock(&hashlock);  if (--fp->f_count == 0) {     /* last reference, remove from list */    idx = HASH(fp);    tfp = fh[idx];    if (tfp == fp) {      fh[idx] = fp->f_next;    } else {      while (tfp->f_next != fp)        tfp = tfp->f_next;      tfp->f_next = fp->f_next;    }    pthread_mutex_unlock(&hashlock);    pthread_mutex_destroy(&fp->f_lock);    free(fp);  } else {    pthread_mutex_unlock(&hashlock);  }}


程序清单11-8  使用读写锁
#include <stdlib.h>#include <pthread.h>struct job {  struct job *j_next;  struct job *j_prev;  pthread_t j_id;               /* tells which thread handles this job */  /* ... more stuff here ... */};struct queue {  struct job *q_head;  struct job *q_tail;  pthread_rwlock_t q_lock;};/* * Initialize a queue. */intqueue_init(struct queue *qp){  int err;  qp->q_head = NULL;  qp->q_tail = NULL;  err = pthread_rwlock_init(&qp->q_lock, NULL);  if (err != 0)    return err;  /* ... continue initialization ... */  return 0;}/* * Insert a job at the head of the queue. */voidjob_insert(struct queue *qp, struct job *jp){  pthread_rwlock_wrlock(&qp->q_lock);  jp->j_next = qp->q_head;  jp->j_prev = NULL;  if (qp->q_head != NULL)    qp->q_head->j_prev = jp;  else    qp->q_tail = jp;            /* list was empty */  qp->q_head = jp;  pthread_rwlock_unlock(&qp->q_lock);}/* * Append a job on the tail of the queue. */voidjob_append(struct queue *qp, struct job *jp){  pthread_rwlock_wrlock(&qp->q_lock);  jp->j_next = NULL;  jp->j_prev = qp->q_tail;  if (qp->q_tail != NULL)    qp->q_tail->j_next = jp;  else    qp->q_head = jp;            /* list was empty */  qp->q_tail = jp;  pthread_rwlock_unlock(&qp->q_lock);}/* * Remove the given job from a queue. */voidjob_remove(struct queue *qp, struct job *jp){  pthread_rwlock_wrlock(&qp->q_lock);  if (jp == qp->q_head) {    qp->q_head = jp->j_next;    if (qp->q_tail == jp)      qp->q_tail = NULL;  } else if (jp == qp->q_tail) {    qp->q_tail = jp->j_prev;    if (qp->q_head == jp)      qp->q_head = NULL;  } else {    jp->j_prev->j_next = jp->j_next;    jp->j_next->j_prev = jp->j_prev;  }  pthread_rwlock_unlock(&qp->q_lock);}/* * Find a job for the given thread ID. */struct job *job_find(struct queue *qp, pthread_t id){  struct job *jp;  if (pthread_rwlock_rdlock(&qp->q_lock) != 0)    return NULL;  for (jp = qp->q_head; jp != NULL; jp = jp->j_next)    if (pthread_equal(jp->j_id, id))      break;  pthread_rwlock_unlock(&qp->q_lock);  return jp;}


程序清单11-9  使用条件变量

#include <pthread.h>struct msg {  struct msg *m_next;  /* ... more stuff ... */};struct msg *workq;pthread_cond_t qready = PTHREAD_COND_INITIALIZER;pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;voidprocess_msg(void){  struct msg *mp;  for (;;) {    pthread_mutex_lock(&qlock);    while (workq == NULL)      pthread_cond_wait(&qready, &qlock);    mp = workq;    workq = mp->m_next;    pthread_mutex_unlock(&qlock);    /* now process the message mp */  }}voidenqueue_msg(struct msg *mp){  pthread_mutex_lock(&qlock);  mp->m_next = workq;  workq = mp;  pthread_mutex_unlock(&qlock);  pthread_cond_signal(&qready);}




0 0
原创粉丝点击