Halo

A magic place for coding

0%

操作系统实验 3-- 线程实验

介绍

   线程是操作系统能够 ** 进行运算调度的最小单位 **。它被包含在进程之中,是进程中的实际运作单位。在这个实验中,我们要充分利用多线程的优点,将复杂的任务细分为多个简单的任务,利用 ** 分治 ** 的思想解决复杂而庞大的问题。本实验包含两个问题:

  • 用线程生成 Fibonacci 数列
  • 多线程矩阵乘法

内容 1

分析

   使用多线程生成 Fibonacci 数列,最后在进程中打印数列结果。
关于多线程编程的主要系统调用:

  • pthread_create ():创建线程。第一个参数是 & pid(pid 为线程号),第二个参数为 & attr(attr 为线程初始化的属性),第三个参数是执行的方法的指针 * runner(即该线程调用名为 runner 的函数),第四个参数是 & para(传入 runner 的参数)。
  • pthread_join ():阻塞调用线程,直到 threadid 所指定的线程终止。** 每个线程只能用 pthread_join () 一次。若多次调用就会发生逻辑错误。**
  • pthread_exit ():终止调用线程。
  • pthread_attr_init ():初始化线程属性为默认属性。
  • pthread_attr_getscope ():获得线程竞争范围。
  • pthread_attr_setscope ():设置线程竞争范围。

代码实现

   生成 Fibonacci 数列本身的原理很简单,需要注意数列前两项需要手动初始化,其后的每一项都可以通过循环来求得。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <pthread.h>
#include <stdio.h>

int fib_arr [1000] = {0};

void *runner(void *param); /* the thread */
int size;
int main(int argc, char *argv []) {
/* Prompt user to enter a number */
printf("Please enter a number: ");
scanf("% d", &size);

while (size < 2) {
printf("Invalid number!!\n");
printf("Please enter a number: ");
scanf("% d", &size);
}

/* Initialize the array */
fib_arr [0] = 0;
fib_arr [1] = 1;

/* Create thread to calculate the fib */
pthread_t tid;
pthread_attr_t attr;

pthread_attr_init (&attr);
pthread_create (&tid, &attr, runner, &fib_arr);
pthread_join (tid, NULL);

/* Print the result */
for (int i = 0; i <= size; i++) {
printf("fib_arr [% d] = % d\n", i, fib_arr [i]);
}

return 0;
}

void *runner(void *param) {
int *temp = (int*) param;
for (int i = 2; i <= size; i++) {
temp [i] = temp [i-1] + temp [i-2];
}
pthread_exit (0);
}

   编译执行上述代码,结果如下:
fib 线程

内容 2

分析

   使用多线程来解决两个矩阵的乘法问题。给出矩阵 A、B,求解 C。对于 C 的每一个元素,我们都创建一个进程来求解。进程的创建、调用等与内容 1 类似。这里特别注意,由于我们传入的参数是一个坐标,因此需要 ** 自定义一个结构 ** 存放两个 int 类型的数据。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define M 3
#define K 2
#define N 3
#define NUM_THREADS 10

int A [M][K] = {{1,4}, {2,5}, {3,6}};
int B [K][N] = {{8,7,6}, {5,4,3}};
int C [M][N] = {0};

struct v {
int i; /* row */
int j; /* column */
};

void *runner(void *param); /* the thread */

int main() {
/* an array of threads to be joined upon */
pthread_t workers [M*N];
pthread_attr_t attr;

/* get the default attributes */
pthread_attr_init (&attr);

for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
struct v *data = (struct v*)malloc(sizeof(struct v));
data->i = i;
data->j = j;

/* create pthreads */
pthread_create (&workers [i*N + j], &attr, runner, (void *) data);
}
}

/* call threads to calculate every element */
for (int i = 0; i < M*N; i++) {
pthread_join (workers [i], NULL);
}

/* print the result */
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
printf("% d ", C [i][j]);
}
printf("\n");
}

return 0;
}

/* calculate the matrix product */
void *runner(void *param) {
struct v *temp = (struct v*) param;
int i = temp->i;
int j = temp->j;

for (int n = 0; n < K; n++) {
C [i][j] += A [i][n]*B [n][j];
}
pthread_exit (0);
}

   编译并执行上述代码,结果如下:
matrix 结果
有兴趣的朋友可以自己改进代码,添加用户输入矩阵的功能。

小结

   这个实验通过两个例子,使用了多线程的编程去求解复杂的问题。通过这个实现,我们学会了如何创建并调用线程,如何传递参数等。关于多线程的实验就分享到这里了,谢谢!

Welcome to my other publishing channels