小作业1:
任务:统计输出素数的个数
思路:
(1)添加一个全局变量:记录素数的个数
(2)在素数统计函数中当判断输入的数据为素数时,num变量加1,在对num进行操作时要先加锁,当数据操作完之后进行解锁。
(3)在main()函数中当所有的线程工作结束时,输出num变量。
出现的问题:在不加锁的情况下最后统计的素数个数会出现重复计算的错误!
小作业2:
任务:每次处理多个元素(注意如果剩余元素不足十个,要特殊处理)
前期准备:在源程序中每个线程获取一个元素判定是否为素数
思路:
(1)首先本程序是创建两个线程进行素数合数判断,当两个线程函数进行工作时它们的索引起始位置分别从0和10开始,注:那个线程运行先抢占到CPU资源就从起始位置0开始,另一个线程则从起始位置10开始
(2)然后从内存中连续读取10个数据,依次进行素数的判断,采用局部变量index++,利用for循环,逻辑详见代码。
(3)每当线程处理完10个数据之后,采用线程锁,更新起始指针的位置,在原来的位置上加10
(4)当最后数据剩余不到10个时,进行特殊处理,剩余几个数据就进行几次处理;(实现逻辑详见代码)
(5)实现效果:源程序中线程每处理完一个数据,就采用线程锁对指针的位置进行修改,线程之间进行多达100次的交互,相互等待的时间过长,这样会浪费大量的cpu资源;这样改进后,在对100个数据进行素数判断时,每完成10个数据处理就进行线程锁交互,大大减少了两个线程间相互影响的次数,从而提高了资源的使用效率。
小作业2核心代码:
/*
============================================================================
Name : Mytest.c
Author : passionYang
Version :1.0
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
/* */
#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; //素数:0,和数:1
for (i = 2; i < inPut / 2; i++) {
if (inPut % i == 0) {
outPut = 1;
break;
}
}
if (outPut == 0) {
/* count num*/
sleep(1);
}
return outPut;
}
void thread(myTest* pMyTest) {
printf("Begin threadID = %u Run!\n", pMyTest->threadID);
int i, n;
int index, inPut, outPut;
int threadID = pMyTest->threadID;
int dataNum = pMyTest->dataNum;
pthread_mutex_lock(pMyTest->pMutIndex);
index = pMyTest->index[0];
pMyTest->index[0] += 10;//第二个运行的线程起始位置从10开始
pthread_mutex_unlock(pMyTest->pMutIndex);
while (index < dataNum) {
//每次处理10个元素
n = dataNum - index ; //查看剩余数据的个数
if (n < 10) //当剩余的数据个数少于10个
{
printf("不足10个数据 = %u Run!\n", n);
for (i = 0; i < n; i++) { //剩余几个数据就进行几次处理
inPut = pMyTest->inPut[index];
outPut = calculate(inPut);
if (outPut == 0) {
/* count num*/
pthread_mutex_lock(pMyTest->pMutIndex); //加锁
num++; //统计素数的个数
pthread_mutex_unlock(pMyTest->pMutIndex); //开锁
}
printf(
"index=%3u, inPut=%8u, outPut=%2u, threadID=%2u \n",
index, inPut, outPut, threadID);
pMyTest->outPut[index] = outPut;
index++;
}
break;//处理完最后的数据要跳出循环
}
for (i = 0; i < 10; i++) { //每次处理10个数据
inPut = pMyTest->inPut[index];
outPut = calculate(inPut);
if (outPut == 0) {
/* count num*/
pthread_mutex_lock(pMyTest->pMutIndex); //加锁
num++; //统计素数的个数
pthread_mutex_unlock(pMyTest->pMutIndex); //开锁
}
printf("index=%3u, inPut=%8u, outPut=%2u, threadID=%2u \n",
index, inPut, outPut, threadID);
pMyTest->outPut[index] = outPut;
index++;
}
pthread_mutex_lock(pMyTest->pMutIndex);
index = pMyTest->index[0];
for (i = 0; i < 10; i++) {
pMyTest->index[0]++; //指针的位置移动10
}
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 = 109;
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);
/*print num*/
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);
}