一.基本功能
1.最简单例子--创建线程
/* * * 创建线程 * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *thread1(void *arg) { printf("this thread1!\n"); } int main(int argc,char **argv) { int ret; pthread_t tid; ret = pthread_create(&tid,NULL,thread1,NULL); sleep(4); return 0; }
2.传递简单参数
/* * * 线程传递参数 * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *thread1(void *arg) { char *prm=NULL; prm=(char*)arg; printf("arg=%s\n",prm); } int main(int argc,char **argv) { int ret; pthread_t tid; ret = pthread_create(&tid,NULL,thread1,(void*)argv[1]); sleep(4); return 0; }
3.传递结构体参数
/* * * 线程传递结构体 * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> typedef struct prm{ int in; char ch[255]; int *p; }oz; void *thread1(void *arg) { oz *prm2 = NULL; prm2=(oz*)arg; printf(" prm:in=%d\n prm:ch=%s\n prm:p=%d\n",prm2->in,prm2->ch,*(prm2->p)); } int main(int argc,char **argv) { int ret; pthread_t tid; oz *prm1=malloc(sizeof(oz)); prm1->in=3; sprintf(prm1->ch,"hello world!"); prm1->p=malloc(sizeof(prm1->p)); *(prm1->p)=123456; ret = pthread_create(&tid,NULL,thread1,(void*)prm1); sleep(4); return 0; }
4.主线程等待子线程结束
/* * * 主线程等待子线程结束 * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *thread1(void *arg) { char *prm=NULL; prm=(char*)arg; printf("arg=%s\n",prm); sleep(5); } int main(int argc,char **argv) { int ret; pthread_t tid; ret = pthread_create(&tid,NULL,thread1,(void*)argv[1]); pthread_join(tid,NULL); return 0; }
5.获取线程id
/* * * 获取线程id * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *thread1(void *arg) { char *prm=NULL; prm=(char*)arg; printf("thread1's id=%lu\n",pthread_self()); sleep(5); } int main(int argc,char **argv) { int ret; pthread_t tid; ret = pthread_create(&tid,NULL,thread1,(void*)argv[1]); printf("main thread's id=%lu\n",pthread_self()); printf("child thread's id=%lu\n",tid); pthread_join(tid,NULL); return 0; }
6.子线程结束释放资源
/* * * 子线程结束释放资源 * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *thread1(void *arg) { char *prm=NULL; prm=(char*)arg; sleep(5); pthread_detach(pthread_self()); } int main(int argc,char **argv) { int ret; pthread_t tid; ret = pthread_create(&tid,NULL,thread1,(void*)argv[1]); pthread_join(tid,NULL); return 0; }
百度百科:pthread_detach
创建一个线程默认的状态是joinable, 如果一个线程结束运行但没有被join,则它的状态类似于进程中的Zombie Process,即还有一部分资源没有被回收(退出状态码),所以创建线程者应该 pthread_join来等待线程运行结束,并可得到线程的退出代码,回收其资源(类似于wait,waitpid)但是调用pthread_join(pthread_id)后,如果该 线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此,比如在Web服务器中当 主线程为每个新来的链接创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的链接),这时可以在子线程中加入代码pthread_detach( pthread_self())或者父线程调用pthread_detach(thread_id)(非阻塞,可立即返回)这将该子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源。
7.创建多个子线程;子线程退出;发送退出信号给子线程
/* * * 创建多个子线程;子线程退出;发送退出信号给子线程 * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *thread2(void *arg) { char *prm=NULL; int i=5; prm=(char*)arg; while(1){ printf("thread2:%s\n",prm); sleep(1); } } void *thread1(void *arg) { char *prm=NULL; int i=5; prm=(char*)arg; while(i--){ printf("thread1:%s\n",prm); sleep(1); }
pthread_exit("omg!");
pthread_detach(pthread_self());
}
int main(int argc,char **argv)
{
int ret;
pthread_t tid1,tid2;
void *join_ret;
ret = pthread_create(&tid1,NULL,thread1,(void*)argv[1]);
pthread_join(tid1,&join_ret);
printf("thread1 exit return:%s\n",(char *)join_ret);
ret = pthread_create(&tid2,NULL,thread2,(void*)argv[2]);
sleep(5);
if(!pthread_cancel(tid2))
printf("cancel pthread2\n");
pthread_join(tid2,NULL);
return 0;
}
8.一些错误的判断及处理
/* * * 错误的判断及处理 * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <errno.h> void *thread2(void *arg) { char *prm=NULL; int i=5; prm=(char*)arg; while(1){ printf("thread2:%s\n",prm); sleep(1); } } void *thread1(void *arg) { char *prm=NULL; int i=5; prm=(char*)arg; while(i--){ printf("thread1:%s\n",prm); sleep(1); } if(pthread_detach(pthread_self())!=0) exit(1); pthread_exit("omg!"); } int main(int argc,char **argv) { int ret; pthread_t tid1,tid2; void *join_ret; ret = pthread_create(&tid1,NULL,thread1,(void*)argv[1]); if(ret!=0){ printf("can't create thread1: %s\n", (char *)strerror(ret)); return -1; } if((ret=pthread_join(tid1,&join_ret))!=0){ printf("pthread_join error %s\n",(char *)strerror(ret)); return ret; } printf("thread1 exit return:%s\n",(char *)join_ret); ret = pthread_create(&tid2,NULL,thread2,(void*)argv[2]); if(ret!=0){ printf("can't create thread2: error num:%d\n", errno); return errno; } sleep(5); if(!pthread_cancel(tid2)){ printf("cancel pthread2\n"); } else pthread_join(tid2,NULL); return 0; }
9.主线程发送信号给子线程
/* * * 主线程发送信号给子线程 * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <signal.h> void kill_handler(int i) { printf("kill_handler\n"); } void *thread1(void *arg) { char *prm=NULL; prm=(char*)arg; printf("arg=%s\n",prm); while(1) ; } int main(int argc,char **argv) { int ret; pthread_t tid; ret = pthread_create(&tid,NULL,thread1,(void*)argv[1]); signal(SIGQUIT,kill_handler); sleep(5); if(pthread_kill(tid,SIGQUIT)==0) printf("signal to pthread!\n"); while(1) ; return 0; }
10.pthread_cleanup_push/pop
/* * * pthread_cleanup_push/pop * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> void cleanup(void *arg) { char* prm=NULL; prm=(char*)arg; printf("cleanup arg=%s\n",prm); } void *thread1(void *arg) { char *prm=NULL; prm=(char*)arg; pthread_cleanup_push(cleanup,(void*)prm); printf("arg=%s\n",prm); pthread_cleanup_pop(1); } int main(int argc,char **argv) { int ret; pthread_t tid; ret = pthread_create(&tid,NULL,thread1,(void*)argv[1]); pthread_join(tid,NULL); return 0; }
二.线程同步
第1部分 线程属性
1.detachstate
/* * * detachstate * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *thread1(void *arg) { char *prm=NULL; prm=(char*)arg; printf("arg=%s\n",prm); sleep(5); } int main(int argc,char **argv) { int ret; pthread_t tid; pthread_attr_t attr; int detachstate; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE); ret = pthread_create(&tid,&attr,thread1,(void*)argv[1]); if(ret!=0){ printf("pthread_create fail!\n"); return ret; } ret = pthread_attr_getdetachstate (&attr, &detachstate); if(ret!=0){ printf("pthread_attr_getdetachstate error!\n"); } if((detachstate==PTHREAD_CREATE_DETACHED)||(detachstate==PTHREAD_CREATE_JOINABLE)){ if(detachstate==PTHREAD_CREATE_DETACHED) printf("PTHREAD_CREATE_DETACHED\n"); else printf("PTHREAD_CREATE_JOINABLE\n"); } pthread_attr_destroy(&attr); pthread_join(tid,NULL); return 0; }
2.guardsize
/* * * guardsize * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *thread1(void *arg) { char *prm=NULL; prm=(char*)arg; printf("arg=%s\n",prm); sleep(5); } int main(int argc,char **argv) { int ret; pthread_t tid; pthread_attr_t attr; size_t guardsize; pthread_attr_init(&attr); pthread_attr_setguardsize(&attr,4093); ret = pthread_create(&tid,&attr,thread1,(void*)argv[1]); if(ret!=0){ printf("pthread_create fail!\n"); return ret; } ret = pthread_attr_getguardsize (&attr, &guardsize); if(ret!=0){ printf("pthread_attr_getguardsize error!\n"); } else{ printf("guardsize=%d\n",guardsize); } pthread_attr_destroy(&attr); pthread_join(tid,NULL); return 0; }
3.inheritsched
/* * * inheritsched * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *thread1(void *arg) { char *prm=NULL; prm=(char*)arg; int ret; pthread_attr_t attr; int inheritsched; pthread_attr_init(&attr); pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED); printf("arg=%s\n",prm); sleep(5); ret = pthread_attr_getinheritsched(&attr, &inheritsched); if(ret!=0){ printf("pthread_attr_getguardsize error!\n"); } if((inheritsched==PTHREAD_INHERIT_SCHED)||(inheritsched==PTHREAD_EXPLICIT_SCHED)){ if(inheritsched==PTHREAD_INHERIT_SCHED) printf("PTHREAD_INHERIT_SCHED\n"); if(inheritsched==PTHREAD_EXPLICIT_SCHED) printf("PTHREAD_EXPLICIT_SCHED\n"); } pthread_attr_destroy(&attr); } int main(int argc,char **argv) { int ret; pthread_t tid; ret = pthread_create(&tid,NULL,thread1,(void*)argv[1]); if(ret!=0){ printf("pthread_create fail!\n"); return ret; } pthread_join(tid,NULL); return 0; }
第2部分 mutex
1.mutex简单应用
//这个例子不好,可能无休止的运行,sum++的位置,及 sum 的判断条件,
使用trylock应该根据函数的返回值来决定是否进行sum的操作这才是正确的操作方式
/* * * mutex简单应用 * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> pthread_mutex_t mutex; int sum=0; void *thread3(void *arg) { char *prm=NULL; prm=(char*)arg; sleep(2); pthread_mutex_trylock(&mutex); while(1){ sum++; if(sum==10) break; printf("thread3:%d\n",sum); sleep(1); } pthread_mutex_unlock(&mutex); } void *thread2(void *arg) { char *prm=NULL; prm=(char*)arg; sleep(1); pthread_mutex_lock(&mutex); while(1){ sum--; if(sum<0) break; printf("thread2:%d\n",sum); sleep(1); } pthread_mutex_unlock(&mutex); } void *thread1(void *arg) { char *prm=NULL; prm=(char*)arg; pthread_mutex_lock(&mutex); while(1){ sum++; if(sum==10) break; printf("thread1:%d\n",sum); sleep(1); } pthread_mutex_unlock(&mutex); } int main(int argc,char **argv) { int ret; pthread_t tid1,tid2,tid3; pthread_mutex_init(&mutex,NULL); ret = pthread_create(&tid1,NULL,thread1,(void*)argv[1]); ret = pthread_create(&tid2,NULL,thread2,(void*)argv[1]); ret = pthread_create(&tid3,NULL,thread2,(void*)argv[1]); pthread_join(tid1,NULL); pthread_join(tid2,NULL); pthread_join(tid3,NULL); pthread_mutex_destroy(&mutex); return 0; }
pthread_mutex_trylock/lock区别
本质区别不就在“try”吗
选哪个取决于场景:
当前线程锁失败,也可以继续其它任务,用trylock合适
当前线程只有锁成功后,才会做一些有意义的工作,那就_lock,没必要轮询trylock
2.进程mutex
//此例程中共享内存使用有些问题,下面的程序若将“尝试注释”代码部分注释,加锁不能堵塞。重新使用一个新的pthread_mutex_t变量,则能正常使用
/* * * 进程mutex * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <sys/shm.h> #include <sys/types.h> #include <sys/ipc.h> typedef struct dev{ int i; pthread_mutex_t mutex; }DEV; int main(int argc,char **argv) { int ret; DEV *device=malloc(sizeof(DEV)); unsigned long j=0; pthread_mutexattr_t mutexattr; int shmid; shmid=shmget(123,sizeof(DEV*),IPC_CREAT|0660); shmctl(shmid,IPC_RMID,0); shmid=shmget(123,sizeof(DEV*),IPC_CREAT|0660); if(shmid==-1) perror("shmget()");
device=(DEV*)shmat(shmid,0,0);pthread_mutexattr_init(&mutexattr); pthread_mutexattr_setpshared(&mutexattr,PTHREAD_PROCESS_SHARED); pthread_mutex_init(&(device->mutex),&mutexattr); ret = fork(); if(ret==-1){ printf("fork error!\n"); } if (ret==0){//将此句放到进城创建之前device=(DEV*)shmat(shmid,0,0);printf("father!\n"); char buffer[1024]; while(1){ pthread_mutex_lock(&(device->mutex)); (device->i)--; printf("father : i = %d\n",(device->i)); //pthread_mutex_unlock(&(device->mutex));//尝试注释 sleep(1); } pthread_mutexattr_destroy(&mutexattr); pthread_mutex_destroy(&(device->mutex)); return 0; } else{ printf("child!\n"); //放到进城创建之前device=(DEV*)shmat(shmid,0,0); while(1){ pthread_mutex_lock(&(device->mutex)); (device->i)++; printf("child : i = %d\n",(device->i)); pthread_mutex_unlock(&(device->mutex)); sleep(1); }
pthread_mutexattr_destroy(&mutexattr); pthread_mutex_destroy(&(device->mutex));return 0; }}
//修改之后的程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/ipc.h>
typedef struct dev
{
int i;
pthread_mutex_t mutex;
}DEV;
int main(int argc,char *argv[])
{
int ret;
DEV *device = malloc(sizeof(DEV));
unsigned long j = 0;
pthread_mutexattr_t mutexattr;
pthread_mutex_t ev;
int shmid;
shmid = shmget(123,sizeof(DEV*),IPC_CREAT|0660);
shmctl(shmid,IPC_RMID,0);
shmid = shmget(123,sizeof(DEV*),IPC_CREAT|0660);
if(shmid == -1)
{
perror("shmget()");
}
device = (DEV*)shmat(shmid,NULL,0);
pthread_mutexattr_init(&mutexattr);
pthread_mutexattr_setpshared(&mutexattr,PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&(device->mutex),&mutexattr);
pthread_mutex_init(&ev,NULL);
ret = fork();
if(ret == -1)
{
printf("fork error\n");
}
if(ret == 0)
{
//father
printf("father\n");
char buffer[1024];
while(1)
{
// pthread_mutex_lock(&ev);
// printf("lock ev\n");
pthread_mutex_lock(&(device->mutex));
printf(" father lock share mutex\n");
// (device->i)--;
(device->i)++;
printf("father: i = %d\n",device->i);
pthread_mutex_unlock(&(device->mutex));
sleep(1);
}
printf("father while out\n");
pthread_mutexattr_destroy(&mutexattr);
pthread_mutex_destroy(&(device->mutex));
return 0;
}
else
{
sleep(5);
printf("child!\n");
device = (DEV*)shmat(shmid,0,0);
while(1)
{
pthread_mutex_lock(&(device->mutex));
(device->i)--;
printf("child: i = %d\n",device->i);
pthread_mutex_unlock(&(device->mutex));
sleep(1);
}
pthread_mutexattr_destroy(&mutexattr);
pthread_mutex_destroy(&(device->mutex));
return 0;
}
}
3.线程mutex
/* * * 线程mutex * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> int i=0; char buffer[1024]; pthread_mutex_t mutex; void *thread2(void *arg) { while(1){ pthread_mutex_lock(&mutex); i++; printf("thread2 %d\n",i); if(fgets(buffer,1024,stdin)!=NULL) pthread_mutex_unlock(&mutex); sleep(1); } } void *thread1(void *arg) { while(1){ pthread_mutex_lock(&mutex); i--; printf("thread1 %d\n",i); if(fgets(buffer,1024,stdin)!=NULL) pthread_mutex_unlock(&mutex); sleep(1); } } int main(int argc,char **argv) { int ret; pthread_t tid1,tid2; pthread_mutexattr_t mutexattr; pthread_mutexattr_init(&mutexattr); pthread_mutexattr_setpshared(&mutexattr,PTHREAD_PROCESS_PRIVATE); pthread_mutex_init(&mutex,&mutexattr); ret = pthread_create(&tid1,NULL,thread1,NULL); ret = pthread_create(&tid1,NULL,thread2,NULL); pthread_join(tid1,NULL); pthread_join(tid2,NULL); pthread_mutexattr_destroy(&mutexattr); pthread_mutex_destroy(&mutex); return 0; }
自己的程序
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
int i=0;
char buffer[1024];
pthread_mutex_t mutex;
void *thread2(void *arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
i++;
printf("thread2:%d\n",i);
if(fgets(buffer,1024,stdin)!=NULL)
{
pthread_mutex_unlock(&mutex);
printf("thread2 unlock\n");
}
sleep(1);
}
}
void *thread1(void * arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
i--;
printf("thread1:%d\n",i);
if(fgets(buffer,1024,stdin)!=NULL)
{
pthread_mutex_unlock(&mutex);
printf("thread1 unlock\n");
}
sleep(1);
}
}
int main(int argc,char *argv[])
{
int ret;
pthread_t tid1,tid2;
pthread_mutexattr_t mutexattr;
pthread_mutexattr_init(&mutexattr);
pthread_mutexattr_setpshared(&mutexattr,PTHREAD_PROCESS_PRIVATE);
pthread_mutex_init(&mutex,&mutexattr);
ret = pthread_create(&tid1,NULL, thread1,NULL);
ret = pthread_create(&tid2,NULL, thread2,NULL);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_mutexattr_destroy(&mutexattr);
pthread_mutex_destroy(&mutex);
return0;
}
第3部分 条件变量
1.线程+mutex+cond
/* * * 线程+mutex+cond * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> pthread_mutex_t mutex; pthread_cond_t cond; int i=0; void *thread2(void *arg) { while(i!=30){ pthread_mutex_lock(&mutex); i++; if(!(i%6)) pthread_cond_signal(&cond); printf("thread2 %d\n",i); pthread_mutex_unlock(&mutex); sleep(1); } } void *thread1(void *arg) { while(i!=30){ pthread_mutex_lock(&mutex); pthread_cond_wait(&cond,&mutex); printf("thread1-%d\n",i); pthread_mutex_unlock(&mutex); sleep(1); } } int main(int argc,char **argv) { int ret; pthread_t tid1,tid2; pthread_condattr_t attr; pthread_mutexattr_t mutexattr; pthread_mutexattr_init(&mutexattr); pthread_mutexattr_setpshared(&mutexattr,PTHREAD_PROCESS_PRIVATE); pthread_condattr_init(&attr); pthread_condattr_setpshared(&attr,PTHREAD_PROCESS_PRIVATE); pthread_mutex_init(&mutex,&mutexattr); pthread_cond_init(&cond,&attr); ret = pthread_create(&tid1,NULL,thread1,(void*)argv[1]); ret = pthread_create(&tid2,NULL,thread2,(void*)argv[1]); pthread_join(tid1,NULL); pthread_join(tid2,NULL); printf("all thread done!\n"); pthread_condattr_destroy(&attr); pthread_cond_destroy(&cond); pthread_mutexattr_destroy(&mutexattr); pthread_mutex_destroy(&mutex); return 0; }
线程+mutex+cond+互锁
//这个程序很烂,上锁和解锁不配对,逻辑混乱,非常容易造成死锁,全局变量i都没有设置,没有全局的结束变量。
关于cond参考之后的关于pthread_cond_wait和pthread_cond_signal博客文章,
/* * * 线程+mutex+cond+互锁 * */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> pthread_mutex_t mutex; pthread_cond_t cond; int i=0; char buffer[1024]; void *thread2(void *arg) { while(i!=30){ pthread_mutex_lock(&mutex); if(fgets(buffer,1024,stdin)!=NULL){ if(buffer[0]!='2'){ pthread_cond_signal(&cond); printf("thread2 pthread_cond_signal\n"); pthread_mutex_unlock(&mutex); } } else{ printf("thread2 pthread_cond_wait\n"); pthread_cond_wait(&cond,&mutex); } printf("thread2 running\n"); sleep(1); } } void *thread1(void *arg) { while(i!=30){ pthread_mutex_lock(&mutex); if(fgets(buffer,1024,stdin)!=NULL){ if(buffer[0]!='1'){ pthread_cond_signal(&cond); printf("thread1 pthread_cond_signal\n"); pthread_mutex_unlock(&mutex); } } else{ printf("thread1 pthread_cond_wait\n"); pthread_cond_wait(&cond,&mutex); } printf("thread1 running\n"); sleep(1); } } int main(int argc,char **argv) { int ret; pthread_t tid1,tid2; pthread_condattr_t attr; pthread_mutexattr_t mutexattr; pthread_mutexattr_init(&mutexattr); pthread_mutexattr_setpshared(&mutexattr,PTHREAD_PROCESS_PRIVATE); pthread_condattr_init(&attr); pthread_condattr_setpshared(&attr,PTHREAD_PROCESS_PRIVATE); pthread_mutex_init(&mutex,&mutexattr); pthread_cond_init(&cond,&attr); ret = pthread_create(&tid1,NULL,thread1,(void*)argv[1]); ret = pthread_create(&tid2,NULL,thread2,(void*)argv[1]); pthread_join(tid1,NULL); pthread_join(tid2,NULL); printf("all thread done!\n"); pthread_condattr_destroy(&attr); pthread_cond_destroy(&cond); pthread_mutexattr_destroy(&mutexattr); pthread_mutex_destroy(&mutex); return 0; }