linux程序设计——多线程(第十二章)
Posted brucemengbm
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux程序设计——多线程(第十二章)相关的知识,希望对你有一定的参考价值。
12.8 多线程
之前,总是让程序的主线程只创建一个线程。这节将演示怎样在同一个程序中创建多个线程,然后怎样以不同于其启动顺序将它们合并在一起。此外,还演示多线程编程时easy出现的时序问题.编敲代码thread8.c
/************************************************************************* > File Name: thread8.c > Description: thread8.c程序创建多个线程。然后以不同于启动顺序将它们合并在一起 > Author: Liubingbing > Created Time: 2015年07月07日 星期二 19时37分45秒 > Other: thread8.c程序存在一个小漏洞,假设主线程执行足够快时,可能改动传递引用的參数thread_index,造成问题.见thread8a.c ************************************************************************/ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> #define NUM_THREADS 6 void *thread_function(void *arg); int main(){ int res; pthread_t a_thread[NUM_THREADS]; void *thread_result; int thread_index; for (thread_index = 0; thread_index < NUM_THREADS; thread_index++) { /* pthread_create创建新线程,这里创建了一个线程ID的数组 */ res = pthread_create(&(a_thread[thread_index]), NULL, thread_function, (void *)&thread_index); if (res != 0) { perror("Thread creation failed"); exit(EXIT_FAILURE); } sleep(1); } printf("Waiting for threads to finish...\n"); /* 主线程中等待合并这些子线程,但并非以创建它们的顺序来合并 */ for (thread_index = NUM_THREADS - 1; thread_index >= 0; thread_index--) { res = pthread_join(a_thread[thread_index], &thread_result); if (res == 0) { printf("Picked up a thread\n"); } else { perror("pthread_join failed"); } } printf("All done\n"); exit(EXIT_SUCCESS); } void *thread_function(void *arg) { int my_number = *(int *)arg; int rand_num; printf("thread_function is running. Argument was %d\n", my_number); /* 创建的线程等待一段随机的时间退出执行 */ rand_num = 1 + (int)(9.0 * rand() / (RAND_MAX + 1.0)); sleep(rand_num); printf("Bye from %d\n", my_number); pthread_exit(NULL); }执行thread8.c,看到例如以下结果:
pthread_t a_thread[NUM_THREADS];然后通过循环创建多个线程。例如以下所看到的:
for (thread_index = 0; thread_index < NUM_THREADS; thread_index++) { res = pthread_create(&(a_thread[thread_index]), NULL, thread_function, (void *)&thread_index); }创建出的线程等待一段随机的时间后退出执行,例如以下所看到的:
void *thread_function(void *arg) { int my_number = *(int *) arg; int rand_num; printf("thread_function is running. Argument was %d\n", my_number); rand_num = 1 + (int)(9.0 * rand() / RAND_MAX + 1.0)); sleep(rand_num); printf("Bye from %d\n", my_number); pthread_exit(NULL); }在主线程中。等待合并这些子线程。但并非以创建它们的顺序来合并。例如以下所看到的:
for (thread_index = NUM_THREADS -1; thread_index >= 0; thread_index--) { res = pthread_join(a_thread[thread_index], &thread_result); ... }这个程序有一个小漏洞,假设将sleep调用从启动线程的循环中删除,它将会变得非常明显。
非常可能会看到一些奇怪的现象,比方一些线程以同样的參数被启动,类似下图:
为什么会出现这种问题?启动线程时,线程函数的參数是一个局部变量,这个变量在循环中被更新。引起问题的代码行是:
for (thread_index = 0; thread_index < NUM_THREADS; thread_index++) { res = pthread_create(&(a_thread[thread_index]), NULL, thread_function, (void *)&thread_index); }假设主线程执行的足够快(由于删除sleep(1)之后,主线程相对新线程就很快了),就可能改变某些线程的參数(即thread_index)。
此时,传递引用不是恰当的选择,而传值是正确的.当对共享变量和多个执行路径没有做到足够重视时,程序就可能出现这种错误行为。
编写线程程序时须要在设计上特别小心。
要改正这个问题。能够直接传递给这个參数的值,例如以下所看到的:
res = pthread_create(&(a_thread[thread_index]), NULL, thread_function, (void *)thread_index);还有改动thread_function函数,例如以下所看到的:
int my_number = (int) arg;
以上是关于linux程序设计——多线程(第十二章)的主要内容,如果未能解决你的问题,请参考以下文章