实验名称
多线程编程实验
实验日期
2024年10月24日
实验目的
- 深入理解多线程编程的概念。
- 实践创建和管理多线程程序的方法。
- 设计并实现一个多线程数独解决方案验证器。
- 设计并实现一个多线程排序应用。
实验环境
- 操作系统:Ubuntu 20.04 LTS
- 编译器:GCC 9.3.0
- 开发工具:Visual Studio Code
实验内容
第一部分:数独解决方案验证器
设计思路
- 定义数据结构:创建一个结构体来存储每个线程需要检查的行和列信息。
- 创建线程:根据任务需求,创建相应数量的线程来检查数独的行、列和小方格。
- 传递参数:使用结构体传递必要的参数给每个线程。
- 结果收集:每个线程完成检查后,将结果存入共享数组中,父线程最后检查这些结果来确定数独解的有效性。
实现代码
#include
#include
#include
#define N 9
typedef struct {
int row;
int col;
} parameters;
int sudoku[N][N] = {
{5, 3, 0, 0, 7, 0, 0, 0, 0},
{6, 0, 0, 1, 9, 5, 0, 0, 0},
{0, 9, 8, 0, 0, 0, 0, 6, 0},
{8, 0, 0, 0, 6, 0, 0, 0, 3},
{4, 0, 0, 8, 0, 3, 0, 0, 1},
{7, 0, 0, 0, 2, 0, 0, 0, 6},
{0, 6, 0, 0, 0, 0, 2, 8, 0},
{0, 0, 0, 4, 1, 9, 0, 0, 5},
{0, 0, 0, 0, 8, 0, 0, 7, 9}
};
int results[11] = { 0 };
void* checkRow(void* arg) {
parameters* p = (parameters*)arg;
int count[10] = { 0 };
for (int i = 0; i < N; ++i) { if (sudoku[p->row][i] == 0) continue;
if (++count[sudoku[p->row][i]] > 1) {
results[p->row] = 0;
pthread_exit(NULL);
}
}
results[p->row] = 1;
pthread_exit(NULL);
}
void* checkCol(void* arg) {
parameters* p = (parameters*)arg;
int count[10] = { 0 };
for (int i = 0; i < N; ++i) { if (sudoku[i][p->col] == 0) continue;
if (++count[sudoku[i][p->col]] > 1) {
results[p->col + N] = 0;
pthread_exit(NULL);
}
}
results[p->col + N] = 1;
pthread_exit(NULL);
}
void* checkSubgrid(void* arg) {
parameters* p = (parameters*)arg;
int count[10] = { 0 };
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) { if (sudoku[p->row + i][p->col + j] == 0) continue;
if (++count[sudoku[p->row + i][p->col + j]] > 1) {
results[p->row / 3 * 3 + p->col / 3 + 2 * N] = 0;
pthread_exit(NULL);
}
}
}
results[p->row / 3 * 3 + p->col / 3 + 2 * N] = 1;
pthread_exit(NULL);
}
int main() {
pthread_t threads[11];
parameters params[11];
for (int i = 0; i < N; ++i) {
params[i].row = i;
params[i].col = 0;
pthread_create(&threads[i], NULL, checkRow, ¶ms[i]);
}
for (int i = 0; i < N; ++i) {
params[i].row = 0;
params[i].col = i;
pthread_create(&threads[i + N], NULL, checkCol, ¶ms[i]);
}
for (int i = 0; i < 9; i += 3) {
for (int j = 0; j < 9; j += 3) {
params[i / 3 * 3 + j / 3].row = i;
params[i / 3 * 3 + j / 3].col = j;
pthread_create(&threads[i / 3 * 3 + j / 3 + 2 * N], NULL, checkSubgrid, ¶ms[i / 3 * 3 + j / 3]);
}
}
for (int i = 0; i < 11; ++i) {
pthread_join(threads[i], NULL);
}
int isValid = 1;
for (int i = 0; i < 11 && isValid; ++i) {
if (!results[i]) {
isValid = 0;
}
}
printf("The Sudoku solution is %s.\n", isValid ? "valid" : "invalid");
return 0;
}
第二部分:多线程排序应用
设计思路
- 分割数据:将原始数组分为两部分。
- 创建排序线程:创建两个线程分别对两部分数据进行排序。
- 创建合并线程:创建一个线程用于合并两个已排序的部分。
- 结果输出:排序完成后,由主程序输出排序结果。
实现代码
#include
#include
#include
#define SIZE 1000
int originalArray[SIZE];
int sortedArray[SIZE];
void* sortThread(void* arg) {
int* range = (int*)arg;
int start = range[0];
int end = range[1];
for (int i = start; i < end; ++i) {
for (int j = i + 1; j < end; ++j) { if (originalArray[i] > originalArray[j]) {
int temp = originalArray[i];
originalArray[i] = originalArray[j];
originalArray[j] = temp;
}
}
}
pthread_exit(NULL);
}
void* mergeThread(void* arg) {
int left = 0, mid = SIZE / 2, right = SIZE;
int i = left, j = mid, k = 0;
while (i < mid && j < right) {
if (originalArray[i] <= originalArray[j]) {
sortedArray[k++] = originalArray[i++];
}
else {
sortedArray[k++] = originalArray[j++];
}
}
while (i < mid) {
sortedArray[k++] = originalArray[i++];
}
while (j < right) {
sortedArray[k++] = originalArray[j++];
}
pthread_exit(NULL);
}
int main() {
pthread_t threads[3];
int ranges[2][2] = { {0, SIZE / 2}, {SIZE / 2, SIZE} };
// 初始化数组
for (int i = 0; i < SIZE; ++i) {
originalArray[i] = rand() % 1000;
}
// 创建排序线程
for (int i = 0; i < 2; ++i) {
pthread_create(&threads[i], NULL, sortThread, &ranges[i]);
}
// 创建合并线程
pthread_create(&threads[2], NULL, mergeThread, NULL);
// 等待所有线程结束
for (int i = 0; i < 3; ++i) {
pthread_join(threads[i], NULL);
}
// 输出排序结果
for (int i = 0; i < SIZE; ++i) {
printf("%d ", sortedArray[i]);
}
printf("\n");
return 0;
}
实验结果
数独解决方案验证器
运行结果:数独解决方案有效。
结果分析:程序成功创建了11个线程,分别检查数独的行、列和小方格。所有线程的结果都正确地传递回父线程,最终判断数独解决方案有效。
多线程排序应用
运行结果:数组成功排序。
结果分析:程序成功创建了3个线程,两个线程分别对数组的前半部分和后半部分进行排序,另一个线程将两个已排序的部分合并。最终输出的数组是有序的。
遇到的问题及解决方案
线程同步问题:在多线程环境中,需要确保线程之间的同步,避免数据竞争。通过使用 pthread_join 函数等待所有线程完成,确保结果的正确性。
内存管理问题:在传递参数时,需要注意内存的分配和释放,避免内存泄漏。使用 malloc 分配内存,并在不再需要时使用 free 释放内存。
总结
通过本次实验,我对多线程编程有了更深入的理解,掌握了创建和管理多线程程序的方法。实验过程中遇到的一些问题也得到了解决,进一步巩固了我的编程技能。未来将继续探索多线程编程在实际应用中的更多可能性。

