代做网站地图,网站开发的服务器,电子商务的网站建设设计书,成都项目网站建设线程的基本概念
线程是进程中的一个单一的执行流。一个进程可以包含多个线程#xff0c;这些线程共享进程中的资源#xff0c;并且在相同的地址空间中执行。多线程是提高应用程序并行性的流行方法。例如#xff0c;在浏览器中#xff0c;不同的标签页可以视作独立的线程。…线程的基本概念
线程是进程中的一个单一的执行流。一个进程可以包含多个线程这些线程共享进程中的资源并且在相同的地址空间中执行。多线程是提高应用程序并行性的流行方法。例如在浏览器中不同的标签页可以视作独立的线程。
通俗解释
简单来说一个程序也就是进程可以有多个小的执行单元这些小的执行单元叫做线程。就像是一个工厂的流水线每条流水线都能并行地完成工作这样整个工厂程序就能更快地处理任务。
在现代应用中多线程是非常有用的。例如在浏览器中每一个标签页可能是一个独立的线程这样如果一个标签页卡住了其他标签页还能继续工作而不会全部停顿。
示例代码使用 Pthread 实现多线程
在 C 语言中我们可以使用 POSIX 线程Pthread库来实现Linux系统下的多线程编程。POSIX 线程库是基于标准的 C/C 线程 API包含在 pthread.h 头文件中。下面我们来写一个简单的多线程程序。
#include pthread.h // 包含 Pthread 库
#include stdio.h // 标准输入输出库
#include stdlib.h // 标准库// 线程要执行的函数
void* myThreadFunction(void* arg) {int threadID *((int*)arg);printf(Hello from thread %d\n, threadID);pthread_exit(NULL); // 线程结束
}int main() {pthread_t threads[3]; // 创建一个线程数组包含3个线程int threadArgs[3]; // 每个线程的参数int rc; // 返回代码for (int i 0; i 3; i) {threadArgs[i] i 1; // 给每个线程分配一个IDprintf(Creating thread %d\n, i 1);rc pthread_create(threads[i], NULL, myThreadFunction, (void*)threadArgs[i]);if (rc) {printf(Error: unable to create thread %d\n, rc);exit(-1);}}// 等待所有线程完成for (int i 0; i 3; i) {pthread_join(threads[i], NULL);}printf(All threads completed.\n);return 0;
}解释代码中的每个部分 头文件包含 #include pthread.h包含 POSIX 线程库的头文件提供多线程的相关函数。#include stdio.h 和 #include stdlib.h 用于输入输出和内存管理。 线程函数 void* myThreadFunction(void* arg)这是每个线程的执行函数。它接受一个参数这里是线程的 ID并打印出线程的问候信息。pthread_exit(NULL)表示线程正常结束。 主函数 pthread_t threads[3]声明一个包含 3 个线程的数组。threadArgs[i] i 1给每个线程分配一个唯一的 ID。pthread_create(...)创建线程并启动 myThreadFunction 函数执行。pthread_join(threads[i], NULL)等待所有线程完成主程序会在所有线程执行完毕之后再继续。
如何编译和运行代码 编译命令 示例输出
Creating thread 1
Creating thread 2
Creating thread 3
Hello from thread 1
Hello from thread 2
Hello from thread 3
All threads completed.2. Pthread 的创建和终止
2.1 Pthread 的声明
在使用 Pthread 时我们需要首先声明线程变量。Pthread 使用 pthread_t 类型来声明线程。
示例
pthread_t threads[NUM_THREAD];pthread_t 是一个结构类型用于标识一个线程。在上面的代码中threads 是一个包含 NUM_THREAD 个线程的数组。
2.2 Pthread 的创建
要创建一个新线程我们可以使用 pthread_create() 函数
int pthread_create(pthread_t *thread, // 线程指针用于接收新创建的线程标识const pthread_attr_t *attr, // 线程属性参数可以用于设置调度策略等void *(*start_routine) (void *), // 线程函数线程开始执行的地方void *arg // 传递给线程函数的参数
);参数解释 thread指向 pthread_t 对象的指针用于存储新创建的线程标识。attr用于设置线程属性的参数可以设置线程的调度策略、分离状态等。通常为 NULL 表示使用默认属性。start_routine线程创建后将执行的函数函数的类型为 void* function(void*)。arg指向传递给线程函数的参数的指针可以为 NULL。 返回值 成功时pthread_create() 返回 0。如果失败则返回错误号且线程标识不确定。
示例代码创建线程
#include pthread.h
#include stdio.h
#include stdlib.h#define NUM_THREADS 3void* threadFunction(void* arg) {int threadID *((int*)arg);printf(Hello from thread %d\n, threadID);pthread_exit(NULL); // 线程完成工作后调用 pthread_exit 显式退出
}int main() {pthread_t threads[NUM_THREADS]; // 声明线程数组int threadArgs[NUM_THREADS]; // 每个线程的参数int rc; // 返回代码for (int i 0; i NUM_THREADS; i) {threadArgs[i] i 1; // 给每个线程分配一个 IDprintf(Creating thread %d\n, i 1);rc pthread_create(threads[i], NULL, threadFunction, (void*)threadArgs[i]);if (rc) {printf(Error: unable to create thread %d\n, rc);exit(-1);}}// 等待所有线程完成for (int i 0; i NUM_THREADS; i) {pthread_join(threads[i], NULL);}printf(All threads completed.\n);return 0;
}在上面的代码中
使用 pthread_create() 创建线程并指定每个线程要执行的函数 threadFunction。通过 pthread_join() 来等待每个线程的完成。
2.3 Pthread 的终止
线程在完成其任务时可以显式地调用 pthread_exit() 函数来终止
void pthread_exit(void *value_ptr);参数解释 value_ptr指向一个整型变量的指针用于存储线程的返回状态。这个变量应该是全局的这样等待该线程的其他线程就可以读取它的返回状态。
线程退出时通常会调用 pthread_exit()确保其他线程能够正确地获知该线程的退出状态。
在前面的示例代码中我们使用了 pthread_exit(NULL)表示线程成功完成其任务且没有特定的返回值。
通俗解释
pthread_create() 就像给每个工人发放工作指令告诉他们该做什么以及如何做而 pthread_exit() 就是让工人在完成任务后报告说“我已经完成了”。
在代码中pthread_create() 创建了线程并传递了一个函数 threadFunction 给它这个函数是线程创建后将要执行的内容。当线程完成其工作后调用 pthread_exit() 来退出。
2.4 示例 1使用 pthread_exit() 函数
在这个示例中我们创建了 5 个线程每个线程执行一个简单的打印任务输出“Hello World!”并带有线程的 ID。以下是完整代码
#include pthread.h // 包含 Pthread 库
#include stdio.h // 标准输入输出库
#include stdlib.h // 标准库#define NUM_THREADS 5 // 定义线程数// 线程函数
void *PrintHello(void *threadid) {int tid (int)threadid; // 将传入的参数转换为整数类型printf(\n%d: Hello World!\n, tid);pthread_exit(NULL); // 线程完成工作后退出
}int main(int argc, char *argv[]) {pthread_t threads[NUM_THREADS]; // 声明一个包含 NUM_THREADS 个线程的数组int rc; // 返回代码int t;// 创建线程for (t 0; t NUM_THREADS; t) {printf(Creating thread %d\n, t);rc pthread_create(threads[t], NULL, PrintHello, (void *)t);if (rc) {printf(ERROR; return code from pthread_create() is %d\n, rc);exit(-1);}}pthread_exit(NULL); // 主线程调用 pthread_exit 以确保子线程能够执行完毕
}代码详细解释 头文件包含 #include pthread.h包含 POSIX 线程库的头文件提供多线程相关函数。#include stdio.h 和 #include stdlib.h 用于输入输出和内存管理。 宏定义 #define NUM_THREADS 5定义线程数量为 5。 线程函数 PrintHello void *PrintHello(void *threadid)每个线程执行的函数。函数参数 threadid 是线程的 ID将它转换为 int 类型以便输出。使用 pthread_exit(NULL) 来退出线程确保线程正常结束。 主函数 main 声明 pthread_t threads[NUM_THREADS]包含 5 个线程的数组。使用 pthread_create() 创建线程循环 NUM_THREADS 次每次创建一个线程并传递线程 ID。如果 pthread_create() 失败打印错误代码并退出程序。主线程调用 pthread_exit(NULL) 以防止主程序退出导致子线程未完成就被强制终止。
输出结果示例
Creating thread 0
Creating thread 1
Creating thread 2
Creating thread 3
Creating thread 44: Hello World!
3: Hello World!
0: Hello World!
1: Hello World!
2: Hello World!解释输出
在这个例子中主线程首先创建 5 个子线程然后每个线程执行 PrintHello 函数来打印 Hello World! 和线程的 ID。
需要注意的是多线程的执行顺序并不确定。因此输出的顺序可能会有所不同例如线程 4 可能先输出而线程 0 可能在最后输出。这是因为每个线程是独立并行执行的具体的执行顺序取决于系统的线程调度。
通俗解释
这个程序的目的是演示如何使用 Pthread 来创建和管理多个线程。在代码中我们创建了 5 个独立的线程每个线程都执行相同的函数 PrintHello只是输出的内容不同——它们会显示各自的线程 ID。
在输出结果中我们看到每个线程的输出顺序是随机的这是因为多线程是并行执行的系统会根据资源的可用性来调度每个线程何时运行。这种随机性是多线程编程的特点也是它的优势所在——可以同时做多个任务从而提高效率。
pthread_exit() 的作用
pthread_exit(NULL) 用于让线程正常结束。它在主线程中调用确保所有的子线程在主线程结束之前都能够顺利完成任务。否则如果主线程执行完毕整个程序可能会直接退出而导致子线程的执行被强制中断。
总结
使用 pthread_create() 来创建线程并传递函数指针作为线程的任务。pthread_exit() 用于显式退出线程确保它们有机会完成其任务。多线程的输出顺序可能是随机的因为线程是并行执行的。 2.5 示例 2pthread_exit() 的影响
在多线程程序中如果主线程即 main() 函数在子线程完成之前退出子线程会自动终止。因此推荐在 main() 中使用 pthread_exit()以确保所有线程都有机会完成其任务。
#include pthread.h // 包含 Pthread 库
#include stdio.h // 标准输入输出库
#include stdlib.h // 标准库
#include unistd.h // 包含 sleep() 函数// 线程函数
void *PrintHello(void *threadid) {sleep(2); // 线程休眠2秒printf(Hello World!\n);pthread_exit(NULL); // 线程正常退出
}int main(int argc, char *argv[]) {pthread_t thread; // 声明一个线程int rc; // 返回代码void *i;printf(In main: create thread\n);rc pthread_create(thread, NULL, PrintHello, i);if (rc) {printf(ERROR; return code from pthread_create() is %d\n, rc);exit(1);}printf(Main thread exits!\n);// 如果取消注释 pthread_exit(NULL)主线程会等待所有线程完成后再退出// pthread_exit(NULL);return 0; // 主线程直接退出
}代码解释 头文件包含 #include pthread.h包含 Pthread 库的头文件用于多线程操作。#include stdio.h 和 #include stdlib.h标准输入输出和内存管理库。#include unistd.h包含 sleep() 函数用于让线程休眠指定时间。 线程函数 PrintHello void *PrintHello(void *threadid)线程的任务是休眠 2 秒后打印 Hello World!。sleep(2)让线程休眠 2 秒。pthread_exit(NULL)线程完成任务后调用 pthread_exit() 进行正常退出。 主函数 main 声明了一个线程 pthread_t thread。使用 pthread_create() 创建线程线程将执行 PrintHello 函数。pthread_exit(NULL) 被注释掉了。如果取消注释则主线程会等待所有子线程完成工作后再退出。
输出结果 如果 pthread_exit(NULL) 被注释掉如代码所示 In main: create thread
Main thread exits!主线程在子线程还没有完成任务时就退出了因此子线程会被强制终止导致 Hello World! 没有被输出。 如果 pthread_exit(NULL) 没有被注释掉 In main: create thread
Main thread exits!
Hello World!主线程调用了 pthread_exit()使得主线程会等待子线程完成所有任务后再退出。这样 Hello World! 会正常输出。
通俗解释
在这个例子中我们创建了一个子线程子线程的任务是等待 2 秒后打印 Hello World!。但是如果主线程main()在子线程完成之前退出那么所有的子线程都会被强制终止。因此我们建议在 main() 中使用 pthread_exit()这样主线程不会立即结束而是等待所有的子线程完成工作。
可以把主线程想象成一场演出中的主持人而子线程是表演者。如果主持人主线程在表演还没结束的时候就离开了那么表演者子线程就不得不中断演出。使用 pthread_exit() 可以确保主持人等到所有表演者完成他们的演出后再离场。
pthread_exit() 的作用
当 pthread_exit() 被调用时主线程不会立即退出它会等待所有的子线程完成。如果主线程直接调用 return程序会结束所有未完成的线程会被强制终止导致一些任务可能无法完成。
总结
pthread_create()用于创建线程主线程可以用它来启动子线程。pthread_exit()用于确保主线程等待所有子线程完成任务后再退出。主线程的退出方式会影响子线程如果主线程直接退出子线程将被强制终止使用 pthread_exit() 则可避免这个问题