APUE 线程 - 程序清单





程序清单11-1 打印线程ID

#include "util.h"
#include<pthread.h> pthread_t ntid; void
printids(const char *s)
{
pid_t pid;
pthread_t tid; 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);
} int
main(void)
{
int err; 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);
} int
main(void)
{
int err;
pthread_t tid1, 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;
}; void
printfoo(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 foo foo = {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);
} int
main(void)
{
int err;
pthread_t tid1, 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> 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)
{
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);
} int
main(void)
{
int err;
pthread_t tid1, 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);
} void
foo_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);
} void
foo_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;
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->f_next;
pthread_mutex_lock(&fp->f_lock);
pthread_mutex_unlock(&hashlock);
/* ... continue initialization ... */
thread_mutex_unlock(&fp->f_lock);
}
return(fp);
} void
foo_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;
int idx; 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);
} void
foo_rele(struct foo *fp) /* release a reference to the object */
{
struct foo *tfp;
int idx; 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;
} void
foo_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;
} void
foo_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.
*/
int
queue_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.
*/
void
job_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.
*/
void
job_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.
*/
void
job_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; void
process_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 */
}
} void
enqueue_msg(struct msg *mp)
{
pthread_mutex_lock(&qlock);
mp->m_next = workq;
workq = mp;
pthread_mutex_unlock(&qlock);
pthread_cond_signal(&qready);
}

APUE 线程 - 程序清单的更多相关文章

  1. APUE信号-程序汇总

    APUE信号-程序汇总      近期重看APUE,发现对于非常多程序的要领还是没有全然理解.所以梳理下便于查看,并且有非常多值得思考的问题. 程序清单10- 1  捕获 SIGUSR1 和 SIGU ...

  2. 程序清单 8-8 exec函数实例,a.out是程序8-9产生的可执行程序

    /* ============================================================================ Name : test.c Author ...

  3. 程序清单8-3 8-4 演示不同的exit值

    //http://blog.chinaunix.net/uid-24549279-id-71355.html /* ========================================== ...

  4. windows phone 8 开发系列(三)程序清单说明与配置

    一 清单文件内容介绍 当我们先建了一个项目之后,我们可以看到vs自动会为我们创建了很多文件,正常人都会先一个个去翻看下每个文件都是干啥的,都主要写了些啥,在这些文件中,在Properies目录下面,我 ...

  5. [C++ Primer Plus] 第11章、使用类(一)程序清单——重载 P408

    程序清单11.4~11.6(运算符重载——添加加法运算符) //1.h class Time { private: int hours; int minutes; public: Time(); Ti ...

  6. [C++ Primer Plus] 第10章、对象和类(一)程序清单——辨析三个const

    程序清单10.1+10.2+10.3 头文件stock.h #ifndef STOCK00_H_ //先测试x是否被宏定义过 #define STOCK00_H_ //如果没有宏定义,就宏定义x并编译 ...

  7. [C++ Primer Plus] 第9章、内存模型和名称空间(一)程序清单

    程序清单9.9(静态存储连续性.无链接性) #include<iostream> using namespace std; ; void strcount(const char *str) ...

  8. [C++ Primer Plus] 第8章、函数探幽(一)程序清单——内联、引用、格式化输入输出、模板、decltype

    程序清单8.1(inline内联函数) #include<iostream> using namespace std; inline double square(double x) {// ...

  9. [C++ Primer Plus] 第7章、函数(一)程序清单——递归,指针和const,指针数组和数组指针,函数和二维数组

    程序清单7.6 #include<iostream> using namespace std; ; int sum_arr(int arr[], int n);//函数声明 void ma ...

随机推荐

  1. IIS实现HTTPS的主机名绑定

    默认情况下,IIS中HTTPS 绑定是无法指定主机名的解决办法:通过手工修改 IIS 配置来实现主机头绑定.打开如下位置的文件. C:\Windows\system32\inetsrv\config\ ...

  2. qemu-img命令

    qemu-img是QEMU的磁盘管理工具,在qemu-kvm源码编译后就会默认编译好qemu-img这个二进制文件.qemu-img也是QEMU/KVM使用过程中一个比较重要的工具,本节对其用法和实践 ...

  3. 关于 vertical-align

    默认情况下(行内基线位置 = 行内元素最大高度): 如果对这个正方形使用 vertival-align:middle.在最大高度的元素上使用负值(middle = - 50% * 元素高度),可以提升 ...

  4. Fiddler使用配置遇到的问题

    针对Fiddler使用遇到的问题记录,方便后期再使用. 1.Chrome导入证书失败,提示"提示由于存储区只读的,存储区已满..." 方法:直接去控制台添加 详细参考:http:/ ...

  5. NOI模拟赛(3.15) sequence(序列)

    Description 小A有N个正整数,紧接着,他打算依次在黑板上写下这N个数.对于每一个数,他可以决定将这个数写在当前数列的最左边或最右边.现在他想知道,他写下的数列的可能的最长严格上升子序列(可 ...

  6. Struts2的线程安全性

    [什么是线程安全性?] 在多线程并发访问的情况下,如果一个对象中的变量的值不会随访问的线程而变化则是线程安全的.反之则称为非线程安全的. [Servlet是线程安全的吗?] [非线程安全的] publ ...

  7. JavaScript中变量、作用域和内存问题(JavaScript高级程序设计第4章)

    一.变量 (1)ECMAScript变量肯能包含两种不同的数据类型的值:基本类型值和引用类型值.基本类型值指的是简单的数据段,引用类型值指那些可能由多个值构成的对象. (2)基本数据类型是按值访问,可 ...

  8. 【转】Quartz.NET

    原文链接:http://www.cnblogs.com/tommyli/archive/2009/02/09/1386644.html Quartz.NET是一个开源的作业调度框架,是OpenSymp ...

  9. jmespath库解析json

    在测试过程中,经常会去JSON中的某个值,jmespath可以是除了jsonpath的另外一种选择. 下面通过几个例子来说明jmespath在python的使用 jmespath python安装 非 ...

  10. 大数据学习——flume拦截器

    flume 拦截器(interceptor)1.flume拦截器介绍拦截器是简单的插件式组件,设置在source和channel之间.source接收到的事件event,在写入channel之前,拦截 ...