本代碼實現統計給定整型數組中素數的個數,其中傳遞給線程的參數是一個結構。
[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;
}