C語言-Linux thread

pthread
POSIX thread為POSIX標準執行緒.定義thread的建立及使用方法
pthread.h中常用的有:
pthread_create、pthread_dispath、pthread_mutex_lock(互斥鎖定)、pthread_mutex_unlock(互斥解鎖)
所有pthread.h可用的function可參考 POSIX thread (pthread) libraries
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html

ps
若在linux下gcc編譯,需加-lpthread參數
ex:
gcc thread.c -o thread -lpthread

……………………………………………..

常見函數說明

pthread_create()

建立thread
函數原形如下
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
參數說明如下
pthread_t *thread: thread id
const pthread_attr_t *restrict attr:thread屬性
void *(*start_routine) (void *):指定要做為thread的function
void *arg:給thread的參數
ps:
thread建立成功後,函數會傳回0
若建立失敗則回傳錯誤代碼,常見代碼為EAGAIN和EINVAL
EAGAIN表示建立的thread數量已超過系統限制的thread數量
EINVAL表示thread屬性不正確

ex:
void printmsg(void);
.... omit ...
pthread_t tid;
pthread_create(&tid, NULL, (void *) printmsg, NULL);
.... omit ...
ex
void *printmsg_a(void *arg);
void *printmsg_b(void *arg);
.... omit ...
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, &printmsg_a, NULL);
pthread_create(&tid2, NULL, &printmsg_b, NULL);
.... omit ...
ex
void *printmsg(void *arg); //argv[1]代入arg
.... omit ...
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
char *argv[];
pthread_create(&tid, &attr, printmsg, argv[1]);
.... omit ...
ex:
void *printmsg( void *arg ){.... //message代入arg
.... omit ...
pthread_t tid1, tid2;
const char *message1 = "thread1";
const char *message2 = "thread2";
iret1 = pthread_create( &tid1, NULL, printmsg, (void*) message1);
iret2 = pthread_create( &tid2, NULL, printmsg, (void*) message2);
.... omit ...


pthread_join()

等待指定的thread結束
函數原型如下
int pthread_join(pthread_t thread, void **thread_return);
參數說明如下
pthread_t thread: thread id
void **thread_return: 用來儲存thread的回傳值
ps:
當等待指定的thread結束時,該函數會被收回
ex:
pthread_join(id,NULL);

pthread_exit()

thread自己結束
函數原型如下
void pthread_exit(void *retval);
ex:
pthread_exit(0);

pthread_key_create

建立thread全域變數

ex
#define NUMTHREADS 3
pthread_key_t glob_var_key;
pthread_t threads[NUMTHREADS];
int i;
pthread_key_create(&glob_var_key,NULL);
for (i=0; i < NUMTHREADS; i++){
pthread_create(&threads[i],NULL,thread_func,NULL);
}
for (i=0; i < NUMTHREADS; i++){
pthread_join(threads[i], NULL);
}
...omit...
void* thread_func(void *arg){
pthread_setspecific(glob_var_key, &glob_var);
...omit...


……………………………………………………………………….

常見範例

顯示資訊
ray@localhost# vi thread.c

#include
#include
void thread(void){
 int i;
 for(i=0;i<2;i++)printf("This is a thread n");
}
int main(void){
 pthread_t id;
 int i,ret;
 pthread_create(&id,NULL,(void *) thread,NULL);
 for(i=0;i<2;i++)printf("This is the process n");
 pthread_join(id,NULL);
 return (0);
}

ray@localhost# gcc thread.c -o thread -lpthread
ray@localhost# ./thread

This is the process
This is the process
This is a thread
This is a thread
ps
每次結果不一樣,這是thread和main process爭奪CPU資源的結果


讀取外部參數做計算
ray@localhost# vi sum_by_thread.c 

#include
#include
int sum;
void *runner(void *param);
int main(int argc, char *argv[]){
 pthread_t tid;
 pthread_attr_t attr;
 pthread_attr_init(&attr);
 pthread_create(&tid,&attr,runner,argv[1]);
 pthread_join(tid,NULL);
 printf("sum=%dn",sum);
}
void *runner(void *param){
 int i, upper= atoi(param);
 sum=0;
 if(upper>0){
  for(i=1,i<=upper;i++)sum+=i;
 }
 pthread_exit(0);
}

ray@localhost# gcc sum_by_thread.c -o sum_by_thread -lpthread
ray@localhost# ./sum_by_thread 3

6


建立三個thread讀取三個檔案
ray@localhost# vi wordthread.c

#include
#include
#include
#define MAX_WLEN 20 //max length of a word
#define MAX_FLEN 6000 //max word in a FILE
#define NUMTID 3 //number of thread
///////////thread
char wordall[3][MAX_FLEN];
void rfile(char ta[2][20]);
////////////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[]){
 int i;
 ///////////// read file by thread
 pthread_t tid[NUMTID];
 char tarray[NUMTID][2][20];
 char buffer[1];
 for(i=0;i< NUMTID;i++){
  sprintf(buffer, "%d", i);
  strcpy(tarray[i][0],buffer); //save thread id
  strcpy(tarray[i][1],argv[i+1]); //save file path
  pthread_create(&tid[i], NULL,(void *) rfile,tarray[i]);
  buffer[0]=' 0 '; //clear array
 }
 for(i=0;i< NUMTID;i++){
  pthread_join(tid[i],NULL);
 }
 /////////// collect word from all file
 char word[MAX_WLEN];
 char *token;
 char c;
 int totalword=0;
 for(i=0;i< NUMTID;i++){
  token = strtok(wordall[i], " ,.n");
  while(token){
   strcpy(word, token);
   for(c=0;c   printf("%s n", word);
   totalword++;
   token = strtok(NULL, " ,.n");
  }
 printf("total word is %d", totalword);
 }
}
//////////////////////////////////////////////////
///////////read file in thread
void rfile(char ta[2][20]){
 FILE *aptr;
 char line[MAX_FLEN];
 aptr = fopen(ta[1],"r");
 while(!feof(aptr)){
  fgets(line, MAX_FLEN, aptr);
  if(feof(aptr)) break;
  strcpy(wordall[atoi(ta[0])], line);
 }
 fclose(aptr);
 pthread_exit(0);
 }
}

ray@localhost# gcc wordthread.c -o wordthread -lpthread
ray@localhost# ./wordthread text1 text2 text3
system
linux
is
…omit..
total word is 9


…………………………………………………

refer
linux man-page http://man7.org/linux/man-pages/man3/
create a global variable http://stackoverflow.com/questions/15100824/how-do-i-create-a-global-variable-that-is-thread-specific-in-c-using-posix-threa
Linux C/C++多线程pthread实例 http://www.metsky.com/archives/550.html
Linux下的多線程編程 http://fanqiang.chinaunix.net/a4/b8/20010811/0905001105_b.html
台灣wiki pthread http://www.twwiki.com/wiki/Pthread