比较线程ID:
#include
int pthread_equal(pthread_t tid1,pthread_t tid2)
获取自身线程ID
#include
pthread_t pthread_self(void);
打印线程ID code 11_2
/*
打印线程ID
*/
#include "apue.h"
#include
pthread_t ntid;
void pr_tids(const char*s){
pid_t pid;
pthread_t tid;
pid = getpid();
tid = pthread_self();
printf("%s pid %lu tid %lu (0x%1x)\n",s,(unsigned long) pid,(unsigned long)tid,(unsigned long)tid);
}
void *thr_fn(void *arg){
pr_tids("new thread: ");
return ((void*)0);
}
int main(){
int err;
err = pthread_create(&ntid,NULL,thr_fn,NULL);
if(err!=0)
printf("cannot create thread\n");
pr_tids("main thread: ");
sleep(1);
exit(0);
}
线程退出 pthrad_exit() code 11_3
#include "apue.h"
#include
/*
线程终止方法:
1.线程从启动例程中返回,返回值是线程的退出码
2.线程可以被同一进程的其他线程取消
3.线程调用pthread_exit
当一个线程通过调用pthread_exit退出或者简单的从例程中返回是,
进程中的其他线程可以通过pthread_join()获得该线程的退出状态
output:
kali@kali:~/Desktop/Linux Study/Hellos/Chapter11$ ./PthreadExit_11_3
thread 1 returning
thread 2 exiting
thread 1 exit code 1
thread 2 exit code 2
*/
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){
printf("cannot create thread 1,err = %d",err);
}
err = pthread_create(&tid2,NULL,thr_fn2,NULL);
if(err!=0){
printf("cannot create thread 2,err = %d",err);
}
err = pthread_join(tid1,&tret);
if(err!=0){
printf("pthread_join,err = %d",err);
}
printf(" thread 1 exit code %ld\n",(long)tret);
err = pthread_join(tid2,&tret);
if(err!=0){
printf("pthread_join,err = %d",err);
}
printf("thread 2 exit code %ld\n",(long)tret);
exit(0);
}
pthread_exit 参数的不正确使用 code 11_4
/*
pthread_exit 参数的不正确使用
output:
kali@kali:~/Desktop/Linux Study/Hellos/Chapter11$ ./PthreadExit_11_4
thread 1
structure at 0x7ed25ee0
foo.a = 1
foo.b = 2
foo.c = 3
foo.d = 4
parent starting thread 2thread 2: ID is 140700961367808
parent:
structure at 0x7ed25ee0
foo.a = 1
foo.b = 0
foo.c = 0
foo.d = 0
*/
#include "apue.h"
#include
struct foo{
int a,b,c,d;
};
void pr_foo(const char* s,const struct foo *fp){
printf("%s",s);
printf("structure at 0x%1x\n",(unsigned long)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};
pr_foo("thread 1\n",&foo);
pthread_exit((void*)&foo);
}
void *thr_fn2(void *arg){
printf("thread 2: ID is %lu\n",(unsigned long)pthread_self());
pthread_exit((void*)0);
}
int main(void){
int err;
pthread_t tid1,tid2;
struct foo *fp; /*这个fp是共享的栈!*/
err = pthread_create(&tid1,NULL,thr_fn1,NULL);
if(err!=0)printf("cannot create thread 1 %d",err);
err = pthread_join(tid1,(void*)&fp);
if(err!=0)printf("cannot join thread 1 %d",err);
sleep(1);
printf("parent starting thread 2");
err = pthread_create(&tid2,NULL,thr_fn2,NULL);
if(err!=0)printf("cannot create thread 2 %d",err);
sleep(1);
pr_foo("parent:\n",fp); /*当主线程访问fp时,fp结构的内容(在tid1的栈上分配已经改变了)*/
exit(0);
}
线程清理处理程序 thread cleanup handler code 11_5
#include "apue.h"
#include
/*
线程可以安排它退出时需要调用的函数---》这样的函数称为线程清理处理程序(thread cleanup handler)
一个线程可以建立多个清理处理程序。
处理程序记录在栈中--》也就是,他们的执行顺序与他们注册时相反
pthread_join()-->获取线程退出状态
*/
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){
return ((void*)2);
}
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
return ((void*)2);
}
int main(void){
int err;
pthread_t tid1,tid2;
void *tret;
err = pthread_create(&tid1,NULL,thr_fn1,NULL);
if(err!=0)printf("cannot create thread 1 %d",err);
err = pthread_join(tid1,tret);
if(err!=0)printf("cannot join thread 1 %d",err);
printf("parent starting thread 2\n");
err = pthread_create(&tid2,NULL,thr_fn2,NULL);
if(err!=0)printf("cannot create thread 2 %d",err);
err = pthread_join(tid2,tret);
if(err!=0)printf("cannot join thread 2 %d",err);
exit(0);
}
互斥锁 mutex code 11_10
#include
#include
struct foo{
int f_count;
pthread_mutex_t f_lock;
int f_id;
};
struct foo* foo_alloc(int id){
struct foo *fp;
if((fp = malloc(sizeof(struct foo))!=NULL))
fp->f_count = 1;
fp->f_id = id;
if(pthread_mutex_init(&fp->f_lock,NULL)!=0){/* pthread_mutex_init()成功返回0 */
free(fp);
retrun NULL;
}
}
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);
}
};
合理安排锁粒度 code 11_11
/*
防止死锁
*/
#include
#include
#define NHASH 29
#define HASH(id) (((unsigned int)id)%NHASH)
struct foo{
int f_count;
pthread_mutex_t f_lock;
int f_id;
struct foo *f_next;/* protected by hashlock */
};
struct foo *fh[NHASH];
pthread_mutex_t hashlock = PTHREAD_MUTEX_INITIALIZER;
struct foo* foo_alloc(int id){ /* allocate the object */
struct foo *fp;
int idx;
if((fp = malloc(sizeof(struct foo))!=NULL)){
fp->f_count = 1;
fp->f_id = id;
if(pthread_mutex_init(&fp->f_lock,NULL)!=0){/* pthread_mutex_init()成功返回0 */
free(fp);
retrun NULL;
}
}
idx = HASH(id);
pthread_mutex_lock(&hashlock);
fp->f_next = fh[idx];
fh[idx] = fp;
pthread_mutex_lock(&fp->f_lock);
pthread_mutex_unlock(&hashlock);
pthread_mutex_unlock(&fp->f_lock);
}
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 */
{
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->f_id);
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);
}
}
struct foo* foo_find(int id){/* find an existing object */
struct foo *fp;
pthread_mutex_lock(&hashlock);
for(fp = fh[HASH(id)];fp!=NULL;fp=fp->f_next){
if(fp->f_id == id){
foo_hold(fp);
break;
}
}
pthread_mutex_unlock(&hashlock);
return fp;
}
pthread_mutex_timelock()避免永久阻塞 code 11_13
/*
使用函数 pthread_mutex_timedlock()避免永久阻塞
当线程试图获取一个已加锁的互斥量时,pthread_mutex_timedlock互斥原语允许绑定线程阻塞时间
当达到超时时间值时,pthread_mutex_timedlock不会对互斥量进行加锁,而是返回错误码 ETIMEOUT
output:
kali@kali:~/Desktop/Linux Study/Hellos/Chapter11$ ./TimeLock_11_13
mutex is lock
current time is 05:36:40 AM
time is now 05:36:50 AM
cannot lock mutex again:Connection timed out
*/
#include "apue.h"
#include
#include
int main(void){
int err;
struct tm *tmp;
struct timespec tout;
char buf[64];
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&lock);
printf("mutex is lock\n");
clock_gettime(CLOCK_REALTIME,&tout);
tmp = localtime(&tout.tv_sec);
strftime(buf,sizeof(buf),"%r",tmp);
printf("current time is %s\n",buf);
tout.tv_sec+=10; /* 10 second from now */
err = pthread_mutex_timedlock(&lock,&tout);
clock_gettime(CLOCK_REALTIME,&tout);
tmp = localtime(&tout.tv_sec);
strftime(buf,sizeof(buf),"%r",tmp);
printf("time is now %s\n",buf);
if(err == 0){
printf("mutex locked again!\n");
}
else{
printf("cannot lock mutex again:%s\n",strerror(err));
}
exit(0);
}
使用屏障同步多个线程 code 11_16
/*
屏障barria是用户协调多个线程并行工作的同步机制。
屏障允许每个线程等待,直到所有的合作线程都达到某一点,然后从该点继续执行
如:pthread_join()
pthread_barrier_init()-->屏障初始化,为屏障分配资源
pthread_barrier_destroy() --释放相应的资源
pthread_barrier_wait() -->调用pthread_barrier_wait的线程在屏障计数,为满足条件时,
会进入休眠状态。如果该线程是最后一个调用pthread_barrier_wait的线程,就满足了屏障技术,所有
线程被唤醒。
output:
kali@kali:~/Desktop/Linux Study/Hellos/Chapter11$ ./Barrier_11_16 > sort.foo
kali@kali:~/Desktop/Linux Study/Hellos/Chapter11$ head -n 10 sort.foo
sort took 0.0812 seconds
1210
3722
4686
5712
6700
8204
11425
18502
22619
*/
#include "apue.h"
#include
#include
#include
#define NTHR 8
#define NUMNUM 800000L
#define TNUM (NUMNUM/NTHR)
long nums[NUMNUM];
long snums[NUMNUM];
pthread_barrier_t b;
//#ifdef SOLARIS
#define heapsort qsort
// #else
// extern int heapsort(void* ,size_t,size_t,int(*)(const void*,const void*));
// #endif
int comparelong(const void* arg1,const void*arg2){
long l1 = *(long *)arg1;
long l2 = *(long *)arg2;
if(l1==l2)return 0;
else if(l1