写一个 2 线程的程序:
首先生成一个从 1 到 1000 万的整数数组,然后用两个线程分别计算数组奇数部分和偶数部分的和,并打印出总的和。(采用 pthread API )
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdlib.h>
#define N 10000000
#define STEP 2
long int integer[N];
void *sumf(void *t)
{
extern long int integer[N];
int ini = *(int *)t;
if (integer[ini] % STEP)
printf("odd sum");
else
printf("even sum");
long int s = 0;
for (int i = ini; i < N; i += STEP)
{
s = s + integer[i];
}
printf(": %ld ", s);
}
int main()
{
// array of integers
extern long int integer[N];
for (int i = 0; i < N; i++)
integer[i] = i + 1;
// sample output
long int s_spl = 0;
for (int i = 0; i < N; i += STEP)
s_spl += integer[i];
printf("sample: odd sum: %ld", s_spl);
s_spl = 0;
for (int i = 1; i < N; i += 2)
s_spl += integer[i];
printf(" even sum: %ld
", s_spl);
// 2 threads
printf("2 threads:
");
pthread_t th1, th2;
// time1
struct timeval t0, t1;
time_t sec0;
suseconds_t msec0;
gettimeofday(&t0, NULL);
int para0 = 0, para1 = 1;
pthread_create(&th1, NULL, sumf, (void *)¶0);
pthread_create(&th1, NULL, sumf, (void *)¶1);
pthread_join(th1, NULL);
pthread_join(th2, NULL);
// time2
gettimeofday(&t1, NULL);
sec0 = t1.tv_sec - t0.tv_sec;
msec0 = t1.tv_usec - t0.tv_usec;
printf("
(glibc) time used:%ld.%ldms
", sec0 * 1000, msec0);
return 0;
}
编译执行的结果:
$ gcc hw4.c -lm -O3 -g -o hw4 -lpthread # 在最后链接pthread的动态库
$ ./hw4
sample: odd sum: 25000000000000 even sum: 25000005000000
2 threads:
odd sumeven sum: 25000000000000 : 25000005000000
(glibc) time used:0.4862ms
可以发现最后输出格式略奇怪,检查 sumf 函数,发现它的结构大致为:if-calc()-prtf(res),由于 pthread_create 产生的线程可能在执行中随机切换(即线程内有序,线程间随机),因此有可能执行完 th1 的 if 段后切换到 th2 执行,从而使输入格式不符合预期(在程序上并没有毛病)。
为了改善这种情况,注意到 printf 提供的是封装的内核态函数的用户态接口,因此考虑把 if 的 print 和 res 的print合并使用 printf,新的 sumf 如下:
void *sumf(void *t)
{
extern long int integer[N];
int ini = *(int *)t;
// 把求和放在前面
long int s = 0;
for (int i = ini; i < N; i += STEP)
{
s = s + integer[i];
}
// 合并输出想要的结果
if (integer[ini] % STEP)
printf("odd sum: %ld ", s);
else
printf("even sum: %ld ", s);
}
得到的结果即修正为:
$ gcc hw4.c -lm -O3 -g -o hw4 -lpthread
$ ./hw4
sample: odd sum: 25000000000000 even sum: 25000005000000
2 threads:
odd sum: 25000000000000 even sum: 25000005000000
(glibc) time used:0.4958ms
该修改的效用得到验证。