多线程基础

创建线程比创建进程快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

posted @ 2011-12-25 19:51  高性能golang  阅读(566)  评论(0编辑  收藏  举报