pthread_create的使用方法
- 格式:doc
- 大小:30.50 KB
- 文档页数:5
pthreads使用示例pthreads是一种在多线程编程中常用的库,它提供了一系列函数和数据结构,方便程序员在多线程环境下进行线程的创建、同步与通信。
本文将以示例的方式介绍pthreads的使用。
## 示例1:线程的创建与销毁在使用pthreads创建线程之前,我们需要先包含头文件`pthread.h`。
下面的示例展示了如何创建一个简单的线程,并在线程中输出一句话。
```c#include <stdio.h>#include <pthread.h>void* thread_func(void* arg) {printf("Hello, pthreads!\n");pthread_exit(NULL);}int main() {pthread_t thread;pthread_create(&thread, NULL, thread_func, NULL);pthread_join(thread, NULL);return 0;}```在上述示例中,首先定义了一个`thread_func`函数,它是线程的入口函数。
在该函数中,我们使用`printf`函数输出一句话。
然后,在`main`函数中,我们调用`pthread_create`函数创建一个新的线程,并将`thread_func`作为线程的入口函数。
最后,我们使用`pthread_join`函数等待线程的结束。
## 示例2:线程的同步与互斥在多线程编程中,线程之间的同步与互斥是非常重要的。
pthreads 提供了一些函数和数据结构,可以帮助我们实现线程的同步与互斥。
下面的示例展示了如何使用互斥锁在多个线程之间实现数据的同步与互斥访问。
```c#include <stdio.h>#include <pthread.h>pthread_mutex_t mutex;int count = 0;void* thread_func(void* arg) {for (int i = 0; i < 1000000; i++) {pthread_mutex_lock(&mutex);count++;pthread_mutex_unlock(&mutex);}pthread_exit(NULL);}int main() {pthread_t threads[10];pthread_mutex_init(&mutex, NULL);for (int i = 0; i < 10; i++) {pthread_create(&threads[i], NULL, thread_func, NULL);}for (int i = 0; i < 10; i++) {pthread_join(threads[i], NULL);}pthread_mutex_destroy(&mutex);printf("Final count: %d\n", count);return 0;}```在上述示例中,我们首先定义了一个互斥锁`mutex`和一个全局变量`count`。
pthread_create 原理-概述说明以及解释1.引言1.1 概述pthread_create是一个用于创建线程的函数,它的作用是创建一个新的线程并执行指定的函数。
在多线程编程中,pthread_create函数是非常重要的一个函数,它可以实现并发执行,提高程序的性能和效率。
通过pthread_create函数,我们可以轻松地创建多个线程来执行不同的任务,从而实现程序的并发执行。
在传统的单线程程序中,所有的任务都是顺序执行的,当遇到阻塞或耗时任务时,整个程序会被阻塞,影响程序的执行效率。
而通过多线程编程,可以将这些任务分配给不同的线程来执行,从而提高程序的并发性和响应速度。
本文将介绍pthread_create函数的原理、用法和应用场景,帮助读者更好地了解和掌握这个重要的多线程操作函数。
通过深入理解pthread_create函数,读者可以更好地利用多线程编程提高程序性能,并更好地应对实际软件开发中的并发需求。
1.2 文章结构:本文将围绕pthread_create函数展开讨论,主要分为三个部分:引言、正文和结论。
在引言部分,将对pthread_create函数进行概述,介绍文章的结构以及明确文章的目的。
在正文部分,将详细介绍pthread_create函数的功能和用法,分析其原理并探讨其应用场景。
在结论部分,将总结pthread_create函数的重要性,提出使用该函数时需要注意的事项,并展望其未来的发展前景。
结构部分的内容1.3 目的本文旨在深入探讨pthread_create函数的原理和应用,帮助读者更好地理解多线程编程的基本原理和实践方法。
通过对pthread_create函数的介绍和分析,读者可以了解到如何使用该函数创建新的线程,并且掌握线程管理的关键技巧。
同时,本文还将探讨pthread_create函数的应用场景,帮助读者更好地应用多线程技术解决实际问题。
通过阅读本文,读者可以深入了解pthread_create函数的实现原理,为提高程序的并发性能和可维护性提供参考。
C语⾔创建线程thread_create()的⽅法在头⽂件 threads.h 中,定义和声明了⽀持多线程的宏、类型和函数。
所有直接与线程相关的标识符,均以前缀 thrd_ 作为开头。
例如,thrd_t 是⼀个对象类型,它标识了⼀个线程。
函数 thrd_create()⽤于创建并开始执⾏⼀个新线程。
函数 thrd_create()的其中⼀个参数为在新线程中需要被执⾏的函数thrd_create()的其中⼀个参数为在新线程中需要被执⾏的函数。
thrd_create()的完整原型是:int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);参数 func 是⼀个指针,它指向在新线程需要被执⾏的函数,⽽ void 指针 arg ⽤于向该函数传递参数。
换句话说,新线程将执⾏函数调⽤ func(arg)。
参数 func 的类型为 thrd_start_t,它被定义为 int(*)(void*)(这是⼀个函数指针,指向⼀个 void 指针作为其参数并返回⼀个 int 值的函数),因此,该线程执⾏的函数返回⼀个 int 类型的值。
程序在后续过程中可以通过调⽤函数 thread_join()获得这个 int 类型的返回值(必要时,需等待该线程执⾏完)。
如果⼀个线程启动成功,函数 thread_create()将新线程写⼊⼀个对象进⾏标识,并通过参数 thr 指向该对象,然后返回宏值thread_success。
在⼤多数情况下,后续的其他操作均依赖于该线程的执⾏结果,并且只有当该线程完成后,才能执⾏其他操作。
函数thread_join()⽤于确保⼀个线程已完成。
它的原型是:int thrd_join(thrd_t thr, int *result);调⽤ thread_join()的线程会被阻塞,直到通过 thr 标识的线程执⾏完成,这⾥“阻塞”(block)指的是:线程会在调⽤thread_join()的位置停留必要的时间。
pthread 编程pthread编程是一种多线程编程的方法,主要用于在C/C++语言中创建和管理线程。
本文将介绍pthread编程的基本概念、使用方法以及一些常见的注意事项。
一、pthread编程的基本概念1. 线程:线程是一个独立的执行序列,可以与其他线程并发执行。
2. 多线程:指在一个程序中同时运行多个线程。
3. 线程库:用于创建和管理线程的函数集合,例如pthread库。
4. 线程标识符:用于唯一标识一个线程的整数值。
5. 线程创建:使用pthread_create函数创建一个新线程。
6. 线程执行:使用pthread_join函数等待一个线程的结束,并获取其返回值。
7. 线程同步:使用互斥锁、条件变量等机制,确保多个线程之间的正确协同执行。
二、pthread编程的使用方法1. 引入pthread库:在C/C++程序中引入pthread库,使用#include <pthread.h>。
2. 创建线程:使用pthread_create函数创建一个新线程,并指定线程执行的函数。
3. 线程执行函数:定义一个函数作为线程的执行函数,函数的参数为void*类型。
4. 线程执行:通过调用pthread_create函数,传入线程执行函数的指针和参数,创建并启动新线程。
5. 线程等待:使用pthread_join函数等待一个线程的结束,并获取其返回值。
6. 线程退出:在线程执行函数中使用pthread_exit函数退出线程,并返回一个值。
7. 线程同步:使用互斥锁、条件变量等机制,确保多个线程之间的正确协同执行。
三、常见的pthread编程注意事项1. 线程安全:在多线程编程中,需要注意多个线程之间对共享资源的访问,避免出现数据竞争等问题。
2. 互斥锁:使用互斥锁(pthread_mutex)来保护共享资源的访问,确保同一时间只有一个线程可以访问。
3. 条件变量:使用条件变量(pthread_cond)来实现线程之间的协调与通信,例如线程的等待和唤醒。
Linux多线程实例练习-pthread_create()Linux多线程实例练习 pthread_create():创建⼀个线程int pthread_create(pthread_t *tidp,const pthread_attr_t *attr,(void*)(*start_rtn)(void*),void *arg);1、代码如下xx_pthread_create.c1 #include <pthread.h>2 #include <stdio.h>3 #include <unistd.h>4 #include <sys/time.h> // for gettimeofday56#define debugMsg(fmt, arg...)\7do{\8 unsigned long lSec = 0; unsigned long lUSec = 0;\9 getTimeuSec(&lSec, &lUSec);\10 printf("[%ld.%06ld]:", lSec, lUSec);\11 printf(fmt, ##arg);\12 }while(0)1314int getTimeuSec(unsigned long *lSec, unsigned long *lUSec)15 {16struct timeval start;17 gettimeofday( &start, NULL );18 *lSec = _sec;19 *lUSec = _usec;2021return0;22 }23void * doPrint(void *arg)24 {25int i = 0;26while(i < 30)27 {28 debugMsg("pthread %2d; main %d\n", i++, *(int*)arg);29 usleep(200000);30 }3132return NULL;33 }3435int main()36 {37 pthread_t pid;38int iX = 123;39 pthread_create(&pid, NULL, doPrint, &iX);40while(iX <= 20 + 123)41 {42 debugMsg("main : %d\n", iX++);43 usleep(300000);44 }4546return0;47 }2、CentOS 下编译通过g++ -g -c -o xx_pthread_create.o xx_pthread_create.cg++ -g -o xx_pthread_create xx_pthread_create.o -lpthread3、运⾏结果[1422496189.763862]:main : 123[1422496189.764341]:pthread 0; main 124[1422496189.965627]:pthread 1; main 124[1422496190.065601]:main : 124[1422496190.166510]:pthread 2; main 125[1422496190.366393]:main : 125[1422496190.367391]:pthread 3; main 126[1422496190.568275]:pthread 4; main 126[1422496190.667215]:main : 126[1422496190.769157]:pthread 5; main 127[1422496190.968039]:main : 127[1422496190.970323]:pthread 6; main 128[1422496191.171922]:pthread 7; main 128[1422496191.269869]:main : 128 [1422496191.373803]:pthread 8; main 129 [1422496191.571696]:main : 129 [1422496191.574958]:pthread 9; main 130 [1422496191.776566]:pthread 10; main 130 [1422496191.873512]:main : 130 [1422496191.977457]:pthread 11; main 131 [1422496192.174348]:main : 131 [1422496192.178362]:pthread 12; main 132 [1422496192.379214]:pthread 13; main 132 [1422496192.475159]:main : 132 [1422496192.580095]:pthread 14; main 133 [1422496192.776006]:main : 133 [1422496192.781267]:pthread 15; main 134 [1422496192.981968]:pthread 16; main 134 [1422496193.076864]:main : 134 [1422496193.182797]:pthread 17; main 135 [1422496193.377656]:main : 135 [1422496193.384089]:pthread 18; main 136 [1422496193.584595]:pthread 19; main 136 [1422496193.678472]:main : 136 [1422496193.785406]:pthread 20; main 137 [1422496193.980296]:main : 137 [1422496193.987689]:pthread 21; main 138 [1422496194.189201]:pthread 22; main 138 [1422496194.281149]:main : 138 [1422496194.390049]:pthread 23; main 139 [1422496194.582987]:main : 139 [1422496194.590944]:pthread 24; main 140 [1422496194.792793]:pthread 25; main 140 [1422496194.883821]:main : 140 [1422496194.993852]:pthread 26; main 141 [1422496195.184826]:main : 141 [1422496195.195665]:pthread 27; main 142 [1422496195.397447]:pthread 28; main 142 [1422496195.486468]:main : 142 [1422496195.598408]:pthread 29; main 143 [1422496195.787329]:main : 143。
createthread用法CreateThread 是windows API函数中的一员之一,它被用于创建一个子线程。
CreateThread主要追求的是更细致地掌控线程的实现,弥补了windows系统CreateProcess函数对进程实现的不足,若要了解CreateProcess用法,可参考Windows API-CreateProcess用法。
一、CreateThread概述CreateThread作为一个windows API函数,其语法如下:HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,SIZE_T dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,__drv_aliasesMem __drv_eval(==0)__drv_aliasesMem LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId);各参数解释如下:1. lpThreadAttributes: 决定新线程是否可以被继承。
若为NULL,新线程就可以被创建进程中的任何线程继承。
若有其他值,则新线程只能被能登录进程对象的线程访问。
2. dwStackSize: 线程栈的大小。
通常该参数保持为0即可,以使用默认的线程栈大小。
3. lpStartAddress: 线程函数的执行地址,其格式必须为DWORD CALLBACK函数的地址。
该线程函数无论返回什么结果,都会被传回给CreateThread的调用者。
回调函数一般不会传入参数,或者直接通过传入指针来获得访问上下文中的一些数据。
4. lpParameter: 指向一个可选的指针,该指针会传递给线程函数(即回调函数)。
5. dwCreationFlags: 线程的创建标志。
可选择的标志如下:· CREATE_SUSPENDED:新线程被调用后暂停执行· STACK_SIZE_PARAM_IS_A_RESERVATION:忽略dwStackSize,取默认值· CREATE_DETACHED:新线程不可被其他线程访问除此之外,还有CREATE_NO_WINDOW等标志,可供根据具体需求选择。
pthread_create 用法1. 引言1.1 概述在多线程编程中,线程的创建是非常重要和常见的操作。
C语言提供了pthread_create函数来创建一个新的线程,并可以指定执行的函数以及传递给该函数的参数。
使用pthread_create函数能够充分发挥多核处理器的并行计算能力,提高程序的运行效率。
1.2 文章结构本文将详细介绍pthread_create函数的用法及相关内容。
首先会介绍该函数的基本概念和作用,然后详细说明其参数意义和使用方法。
接着,会给出一个简单示例代码来展示如何创建一个线程。
随后,还会讨论在线程创建失败时应采取的处理方法,并介绍一些错误处理策略建议。
最后,我们还将探讨线程间通信与同步操作问题,包括共享内存、互斥锁和条件变量等内容。
1.3 目的通过深入研究和理解pthread_create函数及相应内容,读者将能够准确地掌握该函数的用法,并能够利用多线程编写更加高效且可靠的程序。
同时,了解如何正确处理线程创建失败以及如何实现线程间通信与同步操作,对于开发大型复杂程序也具有重要意义。
本文旨在提供一份清晰且全面的pthread_create函数用法指南,帮助读者轻松理解和运用这一重要的多线程编程接口。
2. pthread_create 用法2.1 介绍pthread_create函数pthread_create是一个POSIX标准库函数,用于创建一个新的线程。
它接受四个参数,分别是指向线程标识符的指针、线程属性、指向函数的指针和传递给函数的参数。
2.2 函数参数说明- thread:指向线程标识符的指针。
在调用pthread_create后,新线程的标识符将被存储在该指针所指向的内存中。
- attr:线程属性。
可以为NULL,表示使用默认属性。
- start_routine:指向函数的指针。
新创建的线程将从该函数处开始执行。
- arg:传递给start_routine的参数。
你遇到的 "undefined reference pthread_create" 错误可能是由于你在交叉编译时没有正确链接pthread库。
pthread库是POSIX线程库,是C语言编程中使用多线程必不可少的库。
当你使用交叉编译器编译程序时,需要确保你的编译器知道如何找到并链接目标平台上所需的库。
对于pthread库,你需要确保在编译命令中包含了正确的链接标志。
以下是在交叉编译时使用GCC的一个示例:
bash复制代码arm-linux-gnueabi-gcc -o my_program my_program.c -lpthread
在这个命令中,-lpthread 是链接标志,它告诉编译器链接pthread库。
如果你使用的是其他类型的交叉编译器,你可能需要查看相应的文档以确定正确的链接标志。
如果你正在使用的编译器不支持直接链接pthread库,你可能需要寻找一个适用于你的目标平台的pthread库版本,或者寻找一个等效的线程库。
如果你已经正确链接了pthread库但仍然遇到此错误,那可能是你的代码中并没有正确地调用
pthread_create函数。
请确保你的代码中已经包含了正确的头文件(#include <pthread.h>),并且正确地调用了pthread_create函数。
c语言pthread_create用法pthread_create()函数是C语言中用于创建线程的函数。
它位于头文件pthread.h中,可以通过链接pthread库来使用。
它的原型如下:cint pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* (*start_routine) (void*), void* arg);在这个函数中,第一个参数是指向线程标识符的指针,第二个参数是指向线程属性的指针,第三个参数是指向函数的指针,该函数是新线程所要执行的函数,最后一个参数是传递给start_routine函数的参数。
这个函数的返回值是一个整数,如果成功创建线程,则返回0,否则返回一个非零的错误码。
下面,我将详细解释pthread_create函数的使用方法,并给出几个示例来帮助读者更好地理解和应用该函数。
首先,我们创建一个最简单的线程示例。
这个线程的作用是输出一段文本。
以下是相关代码:c#include <stdio.h>#include <pthread.h>void* print_message(void* arg) {char* message = (char*) arg;printf("%s\n", message);pthread_exit(NULL);}int main() {pthread_t thread;char* message = "Hello, World!";pthread_create(&thread, NULL, print_message, (void*) message);pthread_join(thread, NULL);return 0;}在这个例子中,我们首先定义了一个print_message函数,它的作用是接收一个字符串作为参数,然后打印该字符串。
c语言创建线程例子摘要:1.线程的定义和作用2.C 语言中线程的创建3.创建线程的例子4.总结正文:1.线程的定义和作用线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程实际运行时的基本单位。
线程可以提高程序的执行效率,实现多任务并行处理。
2.C 语言中线程的创建在C 语言中,我们可以使用pthread 库来创建和管理线程。
pthread 是Posix 线程的C 语言实现,提供了多线程编程的API。
3.创建线程的例子下面是一个使用pthread 库创建线程的简单例子:```c#include <stdio.h>#include <stdlib.h>#include <pthread.h>// 定义线程函数void *thread_function(void *arg) {printf("Hello from thread!");return NULL;}int main() {// 创建线程pthread_t thread1, thread2;pthread_create(&thread1, NULL, thread_function, NULL);pthread_create(&thread2, NULL, thread_function, NULL);// 等待线程结束pthread_join(thread1, NULL);pthread_join(thread2, NULL);printf("All threads finished.");return 0;}```在这个例子中,我们定义了一个线程函数`thread_function`,这个函数打印出"Hello from thread!"。
在`main`函数中,我们创建了两个线程,分别调用`thread_function`函数,并使用`pthread_join`函数等待线程结束。
pthread_key_create原理
pthread_key_create是一个POSIX线程库函数,用于创建一个线程特定数据的键。
具体实现原理如下:
1. 当调用pthread_key_create时,该函数首先生成一个全局唯一的键值,即获取一个可以唯一标识该线程特定数据的标识符。
2.然后,该函数会在进程的线程特定数据表中注册该键值。
线程特定数据表存储了当前进程中所有线程的线程特定数据。
3.接下来,该函数会为每个现有的线程分配一个存储该线程特定数据的空间,这个空间可以被所有线程访问。
4. 一旦一个线程调用pthread_key_create创建了一个线程特定数据键,其他线程就可以调用pthread_setspecific为其分配特定值,每个线程都可以对该键存储不同的值。
5.当线程终止时,线程特定数据表会自动释放该线程分配的特定值。
总的来说,pthread_key_create的实现原理是通过分配全局唯一的键值、注册键值到全局线程特定数据表中,并为每个线程分配一个存储该线程特定数据的空间,使得线程可以存储和共享线程特定数据。
pthread_create编译
pthread_create是一个用于创建新线程的函数,它是POSIX线
程库(pthread)中的一部分。
要在C或C++程序中使用
pthread_create函数,首先需要包含pthread.h头文件。
在编译时,需要链接pthread库,以确保程序能够正确调用pthread_create函数。
在使用gcc编译器时,需要使用 -pthread 选项来链接
pthread库。
例如,如果你的源文件名为example.c,你可以使用以
下命令来编译程序:
bash.
gcc -o example example.c -pthread.
这将会将pthread库链接到你的程序中,以便正确调用
pthread_create函数。
另外,如果你使用的是C++编译器,比如g++,同样需要包含pthread.h头文件,并使用 -pthread 选项来链接pthread库。
例
如:
bash.
g++ -o example example.cpp -pthread.
需要注意的是,不同的编译器可能有不同的选项来链接
pthread库,因此在编译时需要查看相应编译器的文档或帮助信息,以确保正确链接pthread库。
总之,要在编译时正确使用pthread_create函数,需要包含pthread.h头文件,并使用适当的选项来链接pthread库,以确保
程序能够正确调用pthread_create函数并创建新线程。
linux之pthread_create实现类的成员函数做参数在C++的类中,普通成员函数不能作为pthread_create的线程函数,如果要作为pthread_create中的线程函数,必须是static !在C语⾔中,我们使⽤pthread_create创建线程,线程函数是⼀个全局函数,所以在C++中,创建线程时,也应该使⽤⼀个全局函数。
static定义的类的成员函数就是⼀个全局函数。
class Thread{private:pthread_t pid;private:static void * start_thread(void *arg) //静态成员函数只能访问静态变量或静态函数,通过传递this指针进⾏调⽤{Thread *ptr = (Thread *)arg;ptr->fpConnectionRunning(); //线程的实体是run}public:int start(){if(pthread_create(&pid,NULL,start_thread,(void *)this) != 0) //´创建⼀个线程(必须是全局函数){return -1;}return0;}virtual void fpConnectionRunning() = 0; //基类中的虚函数要么实现,要么是纯虚函数(绝对不允许声明不实现,也不纯虚)};class SlamData:public Thread{public:SlamData(){if(start()==-1){ std::cout<<"pthread_create error ..."<<std::endl; }}~SlamData();void fpConnectionRunning(); //实现fpConnectionRunning};。
类成员函数作为pthread_create函数参数近⽇需要将线程池封装成C++类,类名为Threadpool。
在类的成员函数exec_task中调⽤pthread_create去启动线程执⾏例程thread_rounter。
编译之后报错如下:spfs_threadpool.cpp: In member function ‘int Threadpool::exec_task(task*)’:spfs_threadpool.cpp:174: error: argument of type ‘void* (Threadpool::)(void*)’ does not match ‘void* (*)(void*)’出现类型不匹配的问题。
因为pthread_create需要的参数类型为void* (*)(void*),⽽thread_rounter作为类的成员函数时其类型是void* (Threadpool::)(void*)的成员函数指针。
我们知道类的成员函数在经过编译器处理之后,会变成带有this指针参数的全局函数,所以类型注定是不会匹配的。
但是如果将thread_rounter声明为static类型,那么编译器会将static形式的函数,转换成不带this指针的全局函数,所以其类型可以与pthread_create需要的参数类型相匹配。
但是类的静态成员函数⽆法访问类的⾮静态成员,不过这可以通过传递this指针解决这个问题。
综上,我的这个问题可以这个样⼦解决。
出问题之前的代码:void *thread_rounter(void *)//线程执⾏函数{//直接访问类的成员}exec_task函数中调⽤:pthread_create(&tid,NULL,thread_rounter,NULL);//启动线程执⾏例程修复这个问题的代码:static void *thread_rounter(void *tmp)/线程执⾏函数{Threadpool *p=(Threadpool *)tmp;//通过p指针间接访问类的⾮静态成员}exec_task函数中调⽤:pthread_create(&tid,NULL,thread_rounter,(void *)this);//启动线程执⾏例程----------------------------------------------------------------------------------------------------------------------在⽹上搜索⼀下还有其他的解决⽅案,摘录如下,为了以⽰尊重标明⽂章来源,感谢原⽂作者。
pthread_create的使用方法.txt人生重要的不是所站的位置,而是所朝的方向。
不要用自己的需求去衡量别人的给予,否则永远是抱怨。
1:pthread_create 函数的安全使用问题做过linux多线程开发的人都会用过pthread_create函数,但是很少人会注意到:主线程在使用pthread_create创建线程时,如果pthread_create 函数的第四个参数(指针参数)传入的值会被主线程随时修改时,这时我们的线程从pthread_create 函数的第四个参数获取的值可能就不是我们想要传入的值了。
看看下面代码:在 main 函数的 for 循环中创建10个线程;每创建一个线程时都把循环变量 i 的值通过 pthread_create 函数的第四个参数传入线程函数中;但是线程获取的值可能不并不是我们想传入的值。
#include <pthread.h>#include <stdio.h>void * threadFunc( void * pm_iPthreadId ){unsigned int iId = * ( unsigned int * ) pm_iPthreadId;printf( "### No.%d pthread start exec; pthread id = %u !\n", iId, pthread_self() );time_t iStartTime = time( NULL );while(1){time_t iTempTime = time( NULL );if ( iTempTime - iStartTime > 2 ){printf( "$$$ NO.%d pthread cirle exec !\n", * ( unsigned int * ) pm_iPthreadId );iStartTime = time( NULL );}}}int main(){pthread_t * pthreadId;pthreadId = new pthread_t[10];for( unsigned int i = 0; i < 10; i++ ){int iRet = pthread_create( pthreadId + i, NULL, threadFunc, &i ); if ( iRet == 0 ){printf( "@@@ create No.%d pthread success; pthreadId = %u !\n", i, pthreadId + i );}}while(1){}return 0;}程序运行结果如下(结果是随机的,每次运行可能都不一样):@@@ create No.0 pthread success; pthreadId = 138174472 ! ### No.1 pthread start exec; pthread id = 3076803472 ! ### No.1 pthread start exec; pthread id = 3087293328 ! @@@ create No.1 pthread success; pthreadId = 138174476 ! @@@ create No.2 pthread success; pthreadId = 138174480 ! ### No.3 pthread start exec; pthread id = 3055823760 ! ### No.3 pthread start exec; pthread id = 3066313616 ! @@@ create No.3 pthread success; pthreadId = 138174484 ! ### No.4 pthread start exec; pthread id = 3045333904 ! @@@ create No.4 pthread success; pthreadId = 138174488 ! @@@ create No.5 pthread success; pthreadId = 138174492 ! ### No.6 pthread start exec; pthread id = 3024354192 ! ### No.6 pthread start exec; pthread id = 3034844048 ! @@@ create No.6 pthread success; pthreadId = 138174496 ! @@@ create No.7 pthread success; pthreadId = 138174500 ! ### No.8 pthread start exec; pthread id = 3003374480 ! ### No.8 pthread start exec; pthread id = 3013864336 ! @@@ create No.8 pthread success; pthreadId = 138174504 ! @@@ create No.9 pthread success; pthreadId = 138174508 ! ### No.10 pthread start exec; pthread id = 2992884624 ! $$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !从以“###”开头的字符结果可以看出:以“###No.0”、“###No.2”、“###No.5、“###No.7”、“###No.7”的字符没有;从这可以看出,我们从pthread_create 函数的第四个参数传入的值是不安全的,应该受到安全保护。
2:此问题原因pthread_create 函数是非阻塞函数;会立即返回,主线程不会在创建线程后阻塞到线程函数执行完后返回,导致线程函数获取到循环变量 i 的值被主线程立即改变。
3:此问题解决方法利用条件变量的保护,在线程函数中把 pthread_create 第四个参数传入的值保存为局部变量。
#include <pthread.h>#include <stdio.h>pthread_cond_t m_Cond;pthread_mutex_t m_Locker;void * threadFunc( void * pm_iPthreadId ){pthread_mutex_lock(&m_Locker);unsigned int iId = * ( unsigned int * ) pm_iPthreadId;printf( "### No.%d pthread start exec; pthread id = %u !\n", iId, pthread_self() );pthread_cond_signal(&m_Cond);pthread_mutex_unlock(&m_Locker);time_t iStartTime = time( NULL );while(1){time_t iTempTime = time( NULL );if ( iTempTime - iStartTime > 2 ){printf( "$$$ NO.%d pthread cirle exec !\n", * ( unsigned int * ) pm_iPthreadId );iStartTime = time( NULL );}}}int main(){pthread_mutex_init(&m_Locker, NULL);pthread_cond_init(&m_Cond, NULL);pthread_t * pthreadId;pthreadId = new pthread_t[10];for( unsigned int i = 0; i < 10; i++ ){pthread_mutex_lock(&m_Locker);int iRet = pthread_create( pthreadId + i, NULL, threadFunc, &i ); if ( iRet == 0 ){printf( "@@@ create No.%d pthread success; pthreadId = %u !\n", i, pthreadId + i );}pthread_cond_wait(&m_Cond, &m_Locker);pthread_mutex_unlock(&m_Locker);}while(1){}return 0;}上面代码运行结果:@@@ create No.0 pthread success; pthreadId = 147902472 !### No.0 pthread start exec; pthread id = 3087563664 !@@@ create No.1 pthread success; pthreadId = 147902476 !### No.1 pthread start exec; pthread id = 3077073808 !@@@ create No.2 pthread success; pthreadId = 147902480 !### No.2 pthread start exec; pthread id = 3066583952 !@@@ create No.3 pthread success; pthreadId = 147902484 !### No.3 pthread start exec; pthread id = 3056094096 !@@@ create No.4 pthread success; pthreadId = 147902488 !### No.4 pthread start exec; pthread id = 3045604240 !@@@ create No.5 pthread success; pthreadId = 147902492 !### No.5 pthread start exec; pthread id = 3035114384 !@@@ create No.6 pthread success; pthreadId = 147902496 !### No.6 pthread start exec; pthread id = 3024624528 !@@@ create No.7 pthread success; pthreadId = 147902500 !### No.7 pthread start exec; pthread id = 3014134672 !@@@ create No.8 pthread success; pthreadId = 147902504 !### No.8 pthread start exec; pthread id = 3003644816 !@@@ create No.9 pthread success; pthreadId = 147902508 ! ### No.9 pthread start exec; pthread id = 2993154960 ! $$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !$$$ NO.10 pthread cirle exec !。