多线程基础
创建线程比创建进程快10~100倍。
#include<pthread.h>
int pthread_create(pthread_t *thread,
pthread_attr_t *attr, //线程的属性
void *(*func)(void *), //指向线程所运行的函数的指针
void *arg); //func函数的参数
void pthread_exit(void *status) 以状态status退出
int pthread_join(pthread_t thread, void **retva) retval存储线程的返回值。即pthread_exit的返回值可以被pthread_join得到
pthread_t pthread_self(void) 获取自己的线程ID
下面是一个多线程对一个公共变量施行自加运行的程序:
#include<stdio.h>
#include<sys/types.h>
#include<pthread.h>
#define NUM 5
int counter=0;
pthread_mutex_t counter_lock=PTHREAD_MUTEX_INITIALIZER;
main(){
pthread_t t[NUM];
void *print_count(void *); //返回void*的函数
int i;
for(i=0;i<NUM;i++)
pthread_create(t+i,NULL,print_count,NULL); //创建NUM个线程,直接把函数名放这儿它就是个函数指针
for(i=0;i<NUM;i++)
pthread_join(t[i],NULL); //等待线程退出
}
void *print_count(void *m){ //其他线程打印counter
int i;
for(i=0;i<NUM;i++){
pthread_mutex_lock(&counter_lock); //加锁
counter++;
pthread_mutex_unlock(&counter_lock);//解锁
}
printf("count=%d\n",counter);
return NULL;
}
由于自加运算不是原子操作,所以在counter++前后分别要加锁和解锁。
counter++是按照counter=counter+1来进行的。先从寄存器中取出counter,让其加1,再把结果复制回内存。
$ ./pth1
count=10
count=5
count=15
count=20
count=25
使用互斥量使程序运行速度变慢,频繁地加锁和解锁,会降低程序的运行效率。好的解决方法是取消互斥量,为每个线程设置自己的计数器,如下所示:
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<ctype.h>
#include<stdlib.h>
struct arg_set{
char *fname;
int count;
};
main(int argc,char *argv[]){
pthread_t t1,t2;
struct arg_set args1,args2;
void *count_words(void*);
if(argc!=3){
printf("usage:$%s file1 file2\n",argv[0]);
exit(1);
}
args1.fname=argv[1];
args1.count=0;
args2.fname=argv[2];
args2.count=0;
pthread_create(&t1,NULL,count_words,(void*)&args1); //向各个线程传递不同的参数
pthread_create(&t2,NULL,count_words,(void*)&args2);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
printf("%5d:%s\n",args1.count,argv[1]);
printf("%5d:%s\n",args2.count,argv[2]);
printf("%5d:total\n",args1.count+args2.count); //对各个线程返回的参数求和
}
void *count_words(void *a){
struct arg_set *args=(struct arg_set*)a;
FILE *fp;
int c,prev='\0';
if((fp=fopen(args->fname,"r"))!=NULL){
while((c=getc(fp))!=EOF){
if(!isalnum(c) && isalnum(prev))
args->count++;
prev=c;
}
fclose(fp);
}
else
perror("fopen:args->fname");
return NULL;
}
$ ./pth2 who1.c hello1.c
270:who1.c
57:hello1.c
327:total
本文来自博客园,作者:高性能golang,转载请注明原文链接:https://www.cnblogs.com/zhangchaoyang/articles/2301193.html