程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 多線程(二):更復雜一點的程序

多線程(二):更復雜一點的程序

編輯:C++入門知識

本代碼實現統計給定整型數組中素數的個數,其中傳遞給線程的參數是一個結構。


[cpp]  #include <stdio.h>  
#include <pthread.h>  
 
int num = 0; 
 
typedef struct myTestType 

    int threadID; 
    int threadNum; 
    int dataNum; 
 
    int *input; 
    int *output; 
    int *index; 
    pthread_mutex_t *pMutIndex; 
}myTest; 
 
int calculate(int input) { 
    int i; 
    int output = 0; 
    for(i=2; i<input/2; i++) { 
        if(input % i == 0) { 
            output = 1; 
            break; 
        } 
    } 
    if(output == 0) 
    { 
        num++; 
        sleep(1); 
    } 
    return output; 

 
void thread(myTest * pMyTest) { 
    printf("Begin threadID=%u run!\n", pMyTest->threadID); 
    int index, input, output; 
    int threadID = pMyTest->threadID; 
    int dataNum = pMyTest->dataNum; 
    pthread_mutex_lock(pMyTest->pMutIndex); 
    index = pMyTest->index[0]; 
    pMyTest->index[0]++; 
    pthread_mutex_unlock(pMyTest->pMutIndex); 
    while(index < dataNum) { 
        input = pMyTest->input[index]; 
        output = calculate(input); 
        printf("index=%3u, input=%8u, output=%2u, threadID=%2u\n", index, input, output, threadID); 
        pMyTest->output[index] = output; 
        pthread_mutex_lock(pMyTest->pMutIndex); 
        index = pMyTest->index[0]; 
        pMyTest->index[0]++; 
        pthread_mutex_unlock(pMyTest->pMutIndex); 
    } 
    pthread_exit(NULL); 

 
int main(void) { 
    int i, ret; 
    int threadNum = 2; 
    myTest * pMyTest = (myTest *)malloc(sizeof(myTest)); 
    pMyTest->dataNum = 100; 
    pMyTest->input = (int *)malloc(sizeof(int)*pMyTest->dataNum); 
    pMyTest->output = (int *)malloc(sizeof(int)*pMyTest->dataNum); 
    for(i=0; i<pMyTest->dataNum;++i) { 
        if(i % 4 == 0) 
            pMyTest->input[i] = (1 << (i%30)) + 1; 
        else 
            pMyTest->input[i] = (7 << (i%16)) + 1; 
    } 
    pMyTest->index = (int *)calloc(1, sizeof(int)); 
 
    pMyTest->pMutIndex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t)); 
    pthread_mutex_init(pMyTest->pMutIndex, NULL); 
 
    pMyTest->threadNum = threadNum; 
    myTest * inMyTest = (myTest *)malloc(sizeof(myTest)*threadNum); 
    for(i=0; i<threadNum; ++i) { 
        memcpy(inMyTest+i, pMyTest, sizeof(myTest)); 
        (inMyTest+i)->threadID = i; 
    } 
    pthread_t * tid = (pthread_t*)malloc(sizeof(pthread_t)*threadNum); 
    printf("Begin create pthread.\n"); 
    for(i=0; i<threadNum; ++i) { 
        ret = pthread_create(tid+i, NULL, (void *)thread, (myTest *)(inMyTest+i)); 
        if(ret != 0) { 
            printf("Create pthread error.\n"); 
            return 0; 
        } 
    } 
    for(i=0; i<threadNum; i++) 
        pthread_join(tid[i], NULL); 
    printf("素數個數:%d\n", num); 
    free(tid); 
    free(inMyTest); 
    pthread_mutex_destroy(pMyTest->pMutIndex); 
    free(pMyTest->pMutIndex); 
    free(pMyTest->input); 
    free(pMyTest->output); 
    free(pMyTest->index); 
    free(pMyTest); 
    return 0; 

#include <stdio.h>
#include <pthread.h>

int num = 0;

typedef struct myTestType
{
 int threadID;
 int threadNum;
 int dataNum;

 int *input;
 int *output;
 int *index;
 pthread_mutex_t *pMutIndex;
}myTest;

int calculate(int input) {
 int i;
 int output = 0;
 for(i=2; i<input/2; i++) {
  if(input % i == 0) {
   output = 1;
   break;
  }
 }
 if(output == 0)
 {
  num++;
  sleep(1);
 }
 return output;
}

void thread(myTest * pMyTest) {
 printf("Begin threadID=%u run!\n", pMyTest->threadID);
 int index, input, output;
 int threadID = pMyTest->threadID;
 int dataNum = pMyTest->dataNum;
 pthread_mutex_lock(pMyTest->pMutIndex);
 index = pMyTest->index[0];
 pMyTest->index[0]++;
 pthread_mutex_unlock(pMyTest->pMutIndex);
 while(index < dataNum) {
  input = pMyTest->input[index];
  output = calculate(input);
  printf("index=%3u, input=%8u, output=%2u, threadID=%2u\n", index, input, output, threadID);
  pMyTest->output[index] = output;
  pthread_mutex_lock(pMyTest->pMutIndex);
  index = pMyTest->index[0];
  pMyTest->index[0]++;
  pthread_mutex_unlock(pMyTest->pMutIndex);
 }
 pthread_exit(NULL);
}

int main(void) {
 int i, ret;
 int threadNum = 2;
 myTest * pMyTest = (myTest *)malloc(sizeof(myTest));
 pMyTest->dataNum = 100;
 pMyTest->input = (int *)malloc(sizeof(int)*pMyTest->dataNum);
 pMyTest->output = (int *)malloc(sizeof(int)*pMyTest->dataNum);
 for(i=0; i<pMyTest->dataNum;++i) {
  if(i % 4 == 0)
   pMyTest->input[i] = (1 << (i%30)) + 1;
  else
   pMyTest->input[i] = (7 << (i%16)) + 1;
 }
 pMyTest->index = (int *)calloc(1, sizeof(int));

 pMyTest->pMutIndex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
 pthread_mutex_init(pMyTest->pMutIndex, NULL);

 pMyTest->threadNum = threadNum;
 myTest * inMyTest = (myTest *)malloc(sizeof(myTest)*threadNum);
 for(i=0; i<threadNum; ++i) {
  memcpy(inMyTest+i, pMyTest, sizeof(myTest));
  (inMyTest+i)->threadID = i;
 }
 pthread_t * tid = (pthread_t*)malloc(sizeof(pthread_t)*threadNum);
 printf("Begin create pthread.\n");
 for(i=0; i<threadNum; ++i) {
  ret = pthread_create(tid+i, NULL, (void *)thread, (myTest *)(inMyTest+i));
  if(ret != 0) {
   printf("Create pthread error.\n");
   return 0;
  }
 }
 for(i=0; i<threadNum; i++)
  pthread_join(tid[i], NULL);
 printf("素數個數:%d\n", num);
 free(tid);
 free(inMyTest);
 pthread_mutex_destroy(pMyTest->pMutIndex);
 free(pMyTest->pMutIndex);
 free(pMyTest->input);
 free(pMyTest->output);
 free(pMyTest->index);
 free(pMyTest);
 return 0;
}
其他代碼都是老師給的。實現素數個數的統計使用了一個全局變量,只加了三行代碼,我認為比較方便。答案代碼中給myTest結構中添加了一個類似int * index的變量來統計素數個數,雖然看起來代碼比使用全局變量繁瑣,但問了一下助教,助教說全局變量效率比較低,占內存神馬的,文章最後給出了不使用全局變量的方法。

不過說實話我不覺得把threadNum和dataNum放在結構裡有多大意義,一個#define就可以搞定了。不過後來想了想,如果設置成define的話,就不能在程序中動態指定線程數和數據量的值了,通過這兩個地方,我發現我還是考慮得有點少...

這次跟前兩次的簡單代碼比較,多了些東西。

首先,在創建線程前,進行了一些額外的工作,這些工作在前面兩次的簡單代碼中均沒有。有兩個指向myTest的指針,其中inMyTest分配了threadNum個myTest大小的內存空間,可以通過(inMyTest+i)分別對各個myTest操作。

memcpy用於在內存中進行拷貝。原型為void *memcpy(void*dest, const void *src, size_t n);由src指向地址為起始地址的連續n個字節的數據復制到以destin指向地址為起始地址的空間內。如果把inMyTest比作一個可以容納threadNum個小方塊的長條形盒子的話,那麼pMyTest就代表一個一個小方塊,memcpy函數的執行過程就是把這些小方塊放到盒子裡的過程。在執行memcpy之前,需要對pMyTest進行分配內存、初始化這一系列工作。

說實話,我第一次見這種產生隨機數(算是隨機數吧...)的方法,移位~

其實復雜參數和簡單參數的傳遞都差不多一樣,只是這個例子中把指針傳進去了而已。

pthread_mutex_lock和pthread_mutex_unlock涉及到互斥鎖。夾在這兩行的代碼只能被一個線程所使用(以防搞亂數據)。但是有可能發生死鎖,這裡先不考慮。執行pthread_mutex_init時可以指定互斥鎖的屬性,有以下四種:

PTHREAD_MUTEX_TIMED_NP,這是缺省值,也就是普通鎖。當一個線程加鎖以後,其余請求鎖的線程將形成一個等待隊列,並在解鎖後按優先級獲得鎖。這種鎖策略保證了資源分配的公平性。

PTHREAD_MUTEX_RECURSIVE_NP,嵌套鎖,允許同一個線程對同一個鎖成功獲得多次,並通過多次unlock解鎖。如果是不同線程請求,則在加鎖線程解鎖時重新競爭。

PTHREAD_MUTEX_ERRORCHECK_NP,檢錯鎖,如果同一個線程請求同一個鎖,則返回EDEADLK,否則與PTHREAD_MUTEX_TIMED_NP類型動作相同。這樣就保證當不允許多次加鎖時不會出現最簡單情況下的死鎖。

PTHREAD_MUTEX_ADAPTIVE_NP,適應鎖,動作最簡單的鎖類型,僅等待解鎖後重新競爭。

順便說一句,calloc和malloc均為分配內存然後返回首地址,但兩者還是有區別的。一個是參數,malloc只接受分配空間大小一個參數,而calloc接受兩個參數,分別為元素的數目和每個元素的大小。另外一個是calloc會自動初始化所分配的內存空間(視類型而定,比如把指針初始化為NULL,把int類型初始化為0)。

下面是不使用全局變量實現統計素數個數的代碼:


[cpp]  #include <stdio.h>  
#include <pthread.h>  
 
 
typedef struct myTestType 

    int threadID; 
    int threadNum; 
    int dataNum; 
 
    int *input; 
    int *output; 
    int *index; 
    int *primeNum; 
    pthread_mutex_t *pMutIndex; 
}myTest; 
 
int calculate(int input) { 
    int i; 
    int output = 0; 
    for(i=2; i<input/2; i++) { 
        if(input % i == 0) { 
            output = 1; 
            break; 
        } 
    } 
    if(output == 0) 
    { 
        sleep(1); 
    } 
    return output; 

 
void thread(myTest * pMyTest) { 
    printf("Begin threadID=%u run!\n", pMyTest->threadID); 
    int index, input, output; 
    int threadID = pMyTest->threadID; 
    int dataNum = pMyTest->dataNum; 
    pthread_mutex_lock(pMyTest->pMutIndex); 
    index = pMyTest->index[0]; 
    pMyTest->index[0]++; 
    pthread_mutex_unlock(pMyTest->pMutIndex); 
    while(index < dataNum) { 
        input = pMyTest->input[index]; 
        output = calculate(input); 
        printf("index=%3u, input=%8u, output=%2u, threadID=%2u\n", index, input, output, threadID); 
        pMyTest->output[index] = output; 
        pthread_mutex_lock(pMyTest->pMutIndex); 
        index = pMyTest->index[0]; 
        pMyTest->index[0]++; 
        if(output == 0) { 
            pMyTest->primeNum[0]++; 
        } 
        pthread_mutex_unlock(pMyTest->pMutIndex); 
    } 
    pthread_exit(NULL); 

 
int main(void) { 
    int i, ret; 
    int threadNum = 2; 
    myTest * pMyTest = (myTest *)malloc(sizeof(myTest)); 
    pMyTest->dataNum = 100; 
    pMyTest->input = (int *)malloc(sizeof(int)*pMyTest->dataNum); 
    pMyTest->output = (int *)malloc(sizeof(int)*pMyTest->dataNum); 
    for(i=0; i<pMyTest->dataNum;++i) { 
        if(i % 4 == 0) 
            pMyTest->input[i] = (1 << (i%30)) + 1; 
        else 
            pMyTest->input[i] = (7 << (i%16)) + 1; 
    } 
    pMyTest->index = (int *)calloc(1, sizeof(int)); 
    pMyTest->primeNum = (int *)calloc(1, sizeof(int)); 
 
    pMyTest->pMutIndex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t)); 
    pthread_mutex_init(pMyTest->pMutIndex, NULL); 
 
    pMyTest->threadNum = threadNum; 
    myTest * inMyTest = (myTest *)malloc(sizeof(myTest)*threadNum); 
    for(i=0; i<threadNum; ++i) { 
        memcpy(inMyTest+i, pMyTest, sizeof(myTest)); 
        (inMyTest+i)->threadID = i; 
    } 
    pthread_t * tid = (pthread_t*)malloc(sizeof(pthread_t)*threadNum); 
    printf("Begin create pthread.\n"); 
    for(i=0; i<threadNum; ++i) { 
        ret = pthread_create(tid+i, NULL, (void *)thread, (myTest *)(inMyTest+i)); 
        if(ret != 0) { 
            printf("Create pthread error.\n"); 
            return 0; 
        } 
    } 
    for(i=0; i<threadNum; i++) 
        pthread_join(tid[i], NULL); 
    printf("素數個數:%d\n", pMyTest->primeNum[0]); 
    free(tid); 
    free(inMyTest); 
    pthread_mutex_destroy(pMyTest->pMutIndex); 
    free(pMyTest->pMutIndex); 
    free(pMyTest->input); 
    free(pMyTest->output); 
    free(pMyTest->index); 
    free(pMyTest->primeNum); 
    free(pMyTest); 
    return 0; 

#include <stdio.h>
#include <pthread.h>


typedef struct myTestType
{
 int threadID;
 int threadNum;
 int dataNum;

 int *input;
 int *output;
 int *index;
 int *primeNum;
 pthread_mutex_t *pMutIndex;
}myTest;

int calculate(int input) {
 int i;
 int output = 0;
 for(i=2; i<input/2; i++) {
  if(input % i == 0) {
   output = 1;
   break;
  }
 }
 if(output == 0)
 {
  sleep(1);
 }
 return output;
}

void thread(myTest * pMyTest) {
 printf("Begin threadID=%u run!\n", pMyTest->threadID);
 int index, input, output;
 int threadID = pMyTest->threadID;
 int dataNum = pMyTest->dataNum;
 pthread_mutex_lock(pMyTest->pMutIndex);
 index = pMyTest->index[0];
 pMyTest->index[0]++;
 pthread_mutex_unlock(pMyTest->pMutIndex);
 while(index < dataNum) {
  input = pMyTest->input[index];
  output = calculate(input);
  printf("index=%3u, input=%8u, output=%2u, threadID=%2u\n", index, input, output, threadID);
  pMyTest->output[index] = output;
  pthread_mutex_lock(pMyTest->pMutIndex);
  index = pMyTest->index[0];
  pMyTest->index[0]++;
  if(output == 0) {
   pMyTest->primeNum[0]++;
  }
  pthread_mutex_unlock(pMyTest->pMutIndex);
 }
 pthread_exit(NULL);
}

int main(void) {
 int i, ret;
 int threadNum = 2;
 myTest * pMyTest = (myTest *)malloc(sizeof(myTest));
 pMyTest->dataNum = 100;
 pMyTest->input = (int *)malloc(sizeof(int)*pMyTest->dataNum);
 pMyTest->output = (int *)malloc(sizeof(int)*pMyTest->dataNum);
 for(i=0; i<pMyTest->dataNum;++i) {
  if(i % 4 == 0)
   pMyTest->input[i] = (1 << (i%30)) + 1;
  else
   pMyTest->input[i] = (7 << (i%16)) + 1;
 }
 pMyTest->index = (int *)calloc(1, sizeof(int));
 pMyTest->primeNum = (int *)calloc(1, sizeof(int));

 pMyTest->pMutIndex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
 pthread_mutex_init(pMyTest->pMutIndex, NULL);

 pMyTest->threadNum = threadNum;
 myTest * inMyTest = (myTest *)malloc(sizeof(myTest)*threadNum);
 for(i=0; i<threadNum; ++i) {
  memcpy(inMyTest+i, pMyTest, sizeof(myTest));
  (inMyTest+i)->threadID = i;
 }
 pthread_t * tid = (pthread_t*)malloc(sizeof(pthread_t)*threadNum);
 printf("Begin create pthread.\n");
 for(i=0; i<threadNum; ++i) {
  ret = pthread_create(tid+i, NULL, (void *)thread, (myTest *)(inMyTest+i));
  if(ret != 0) {
   printf("Create pthread error.\n");
   return 0;
  }
 }
 for(i=0; i<threadNum; i++)
  pthread_join(tid[i], NULL);
 printf("素數個數:%d\n", pMyTest->primeNum[0]);
 free(tid);
 free(inMyTest);
 pthread_mutex_destroy(pMyTest->pMutIndex);
 free(pMyTest->pMutIndex);
 free(pMyTest->input);
 free(pMyTest->output);
 free(pMyTest->index);
 free(pMyTest->primeNum);
 free(pMyTest);
 return 0;
}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved