记录LINUX系统下的C++线程使用,不涉及保密项目。
c++ 11 之后有了标准的线程库:std::thread
。但在LINUX下pthread
使用的多一点,因此本文主要学习pthread
的一些用法。
基本概念
线程基本概念待续。。。。
线程的基本使用
线程的创建与退出
函数原型:int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine)(void*), void *arg);
--- thread: 线程标识符,即线程ID,标识唯一线程;
--- attr : 一个不透明的属性对象,可以被用来设置线程属性。您可以指定线程属性对象,也可以使用默认值 NULL;
--- start_routine: 线程运行函数起始地址,一旦线程被创建就会执行;
--- arg: 运行函数的参数。它必须通过把引用作为指针强制转换为 void 类型进行传递。如果没有传递参数,则使用 NULL;
--- 创建成功,返回0;失败,则返回错误号。
函数原型:void pthread_exit(void *value_ptr);
--- 没有返回值。最后一个线程终止后,该进程以状态0退出;
pthread_study1.cpp1 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
|
#include <iostream> #include <cstdlib> #include <pthread.h>
using namespace std; #define NUM_THREADS 5
void *PrintHello(void *threadid) { int tid = *((int*)threadid); cout << "Hello Pthread!" << endl; cout << "当前线程 ID: " << tid << endl; }
int main () { pthread_t threads[NUM_THREADS]; int indexes[NUM_THREADS]; int i, rec; for( i=0; i < NUM_THREADS; i++ ){ cout << "创建线程:" << i << endl; indexes[i] = i; rec = pthread_create(&threads[i], NULL, PrintHello, (void *)&(indexes[i])); if (rec){ cout << "Error:无法创建线程," << rec << endl; exit(-1); } } pthread_exit(NULL); }
|
pthread_study1 运行结果
pthread_study2.cpp1 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
|
#include <iostream> #include <cstdlib> #include <pthread.h>
using namespace std; #define NUM_THREADS 5
struct thread_data{ int thread_id; char *message; };
void *PrintHello(void *threadarg) { struct thread_data *my_data; my_data = (struct thread_data *) threadarg; cout << "Thread ID : " << my_data->thread_id << endl; cout << " Message : " << my_data->message << endl; pthread_exit(NULL); }
int main () { pthread_t threads[NUM_THREADS]; struct thread_data td[NUM_THREADS]; int i,rec;
for( i=0; i < NUM_THREADS; i++ ){ cout <<"main() : creating thread, " << i << endl; td[i].thread_id = i; td[i].message = (char*)"This is message"; rec = pthread_create(&threads[i], NULL, PrintHello, (void *)&td[i]); if (rec){ cout << "Error:unable to create thread," << rec << endl; exit(-1); } } pthread_exit(NULL); }
|
pthread_study2 运行结果
线程的阻塞与分离
函数原型:int pthread_join(pthread_t thread, void **value_ptr);
--- thread: 线程标识符,即线程ID,标识唯一线程;
--- value_ptr: 用户定义的指针,用来存储被等待线程的返回值;
--- 创建成功,返回0;失败,则返回错误号。
函数原型:int pthread_detach(pthread_t thread);
--- thread: 线程标识符,即线程ID,标识唯一线程;
--- 创建成功,返回0;失败,则返回错误号。
pthread_study3.cpp1 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
|
#include <iostream> #include <stdio.h> //使用printf #include <cstdlib> #include <pthread.h>
using namespace std; #define INDEX 3
static int count = 0;
void *Thread_Run(void *threadid){ pthread_detach(pthread_self()); int tid = *((int*)threadid); cout << "当前线程 ID: " << tid << endl; for(int i =0; i<5; i++){ count++; printf("Current count is %d\n",count); } }
int main(void) { pthread_t ThreadID[INDEX]; for(int i=0; i < INDEX; i++ ){ pthread_create(&ThreadID[i],NULL,Thread_Run,(void *)&(i)); printf("创建线程INDEX:%d\n",i); int rec = pthread_join(ThreadID[i],NULL); if(rec){ printf("线程阻塞失败!\n"); abort(); } } printf("The count is: %d\n",count); pthread_exit(NULL); return 0; }
|
pthread_study3 运行结果
可以看到线程阻塞后,按照子线程ID的顺序执行任务。当子线程任务执行完后,才开始执行主线程任务。
在默认情况下通过pthread_create函数创建的线程是非分离属性的,由pthread_create函数的第二个参数决定,在非分离的情况下,当一个线程结束的时候,它所占用的系统资源并没有完全真正的释放,也没有真正终止。只有在pthread_join函数返回时,该线程才会释放自己的资源。或者是设置在分离属性的情况下,一个线程结束会立即释放它所占用的资源。
通常是主线程使用pthread_create()创建子线程以后,一般可以调用pthread_detach(threadid)分离刚刚创建的子线程,这里的threadid是指子线程的threadid;如此以来,该子线程止时底层资源立即被回收;被创建的子线程也可以自己分离自己,子线程调用pthread_detach(pthread_self())就是分离自己,因为pthread_self()这个函数返回的就是自己本身的线程ID。
线程执行的互斥和同步
未完待续
信号量控制线程的执行顺序
未完待续
参考