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