【C++】多线程

【C++】多线程
多线程线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流一个进程中可以并发多个线程每条线程并行执行不同的任务。多线程是多任务处理的一种特殊形式。一般情况下两种类型的多任务处理基于进程和基于线程。基于进程的多任务处理是程序的并发执行。基于线程的多任务处理是同一程序的片段的并发执行。并发多个任务在时间片段内交替执行表现出同时进行的效果。并行多个任务在多个处理器或处理器核上同时执行。C 多线程编程涉及在一个程序中创建和管理多个并发执行的线程。实现多线程在C 11 新特性中std::thread对linux中的pthread和windows中的Win32 API进行封装支持跨平台、移动语义等特点本文主要使用std::thread对pthread和Thread简单使用。使用windows.h实现windows下的原生API进行创建线程。接口//创建线程 HANDLE CreateThread( _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, // 安全属性 _In_ SIZE_T dwStackSize, // 堆栈大小 _In_ LPTHREAD_START_ROUTINE lpStartAddress, // 线程函数地址 _In_opt_ LPVOID lpParameter, // 线程参数 _In_ DWORD dwCreationFlags, // 创建标志 _Out_opt_ LPDWORD lpThreadId // 接收线程ID ); //关闭句柄 CloseHandle( _In_ _Post_ptr_invalid_ HANDLE hObject ); //待线程结束 //等待事件、信号量等同步对象 DWORD WaitForSingleObject( _In_ HANDLE hHandle, // 要等待的对象句柄 _In_ DWORD dwMilliseconds // 超时时间毫秒 ); // 使用标志变量让线程自然退出 // 使用事件对象通知线程退出 BOOL TerminateThread( _In_ HANDLE hThread, // 要终止的线程句柄 _In_ DWORD dwExitCode // 线程退出码 ); // 检查线程是否仍在运行 // 获取线程的执行结果 // 调试和错误处理 BOOL GetExitCodeThread( _In_ HANDLE hThread, // 线程句柄 _Out_ LPDWORD lpExitCode // 接收退出码的指针 ); // 设置当前线程属性优先级、亲和性等 // 在线程函数中操作自身 HANDLE GetCurrentThread(VOID); // 无参数返回当前线程伪句柄实现#include windows.h #include iostream using namespace std; DWORD WINAPI threadrun(LPVOID lpParamter) { for (int i 0; i 10; i) { cout Threadrun: i endl; Sleep(50); } return 0; } int main() { HANDLE hThread CreateThread(NULL, 0, threadrun, NULL, 0, NULL); CloseHandle(hThread); //CloseHandle只是关闭了句柄并不会终止线程。但是如果主线程退出进程会终止所有线程都会结束。 for (int i 0; i 10; i) { cout Main i endl; Sleep(10); } //WaitForSingleObject(hThread, INFINITE); //等待线程完成 前提是hThread没有关闭 return 0; }使用pthread实现接口// 创建线程 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); // 线程退出 void pthread_exit(void *retval); // 等待线程结束 int pthread_join(pthread_t thread, void **retval); // 分离线程 int pthread_detach(pthread_t thread); // 取消线程 int pthread_cancel(pthread_t thread); // 获取当前线程ID pthread_t pthread_self(void); // 比较线程ID int pthread_equal(pthread_t t1, pthread_t t2); // 初始化线程属性 int pthread_attr_init(pthread_attr_t *attr); // 销毁线程属性 int pthread_attr_destroy(pthread_attr_t *attr); // 设置分离状态 int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); // 获取分离状态 int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate); // 设置堆栈大小 int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); // 设置调度策略 /* * 参数policy - * SCHED_FIFO 先进先出 * SCHED_RR 轮转 * SCHED_OTHER 其他默认 */ int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);实现#include pthread.h // POSIX 线程库头文件 #include stdio.h // 标准输入输出头文件 #include stdlib.h // 标准库头文件包含exit等函数 #include unistd.h // Unix标准库头文件包含getpid(), sleep()等系统调用 #include iostream // C标准输入输出流 #include cstring using namespace std; // 使用std命名空间 // 线程函数 - 子线程的入口点 // 参数threadid - 传递给线程的参数这里用作线程标识符 // 返回值void* - 线程退出时可以返回一个指针这里返回NULL void *PrintThread(void *threadid) { // 获取当前线程ID的方式 // 使用pthread_self()获取POSIX线程IDpthread_t类型 pthread_t id pthread_self(); pid_t tid getpid(); // 这获取的是进程ID不是线程ID cout ChildThread: pid tid endl; // 这里打印的是进程ID cout ChildSelf: id id endl; for(int i 0; i 100; i){ cout i endl; sleep(1); // 休眠1秒模拟耗时操作 } // 线程退出 pthread_exit(NULL); // 显式退出线程参数NULL表示不返回任何值 // 或者直接: return NULL; // 等效的退出方式 } int main(int argc, char *argv[]) { // 获取当前进程ID注意主线程也在同一个进程中 pid_t tid getpid(); // 获取当前进程ID cout main thread pid tid endl; // 打印主线程所在进程的ID pthread_t id pthread_self(); cout main Self: id id endl; pthread_t thread; // 线程句柄/标识符用于引用创建的线程 pthread_attr_t attr; //线程属性对象 int result; // 存储函数返回码return code long param 1; // 线程参数这里作为线程ID使用值为1 result pthread_attr_init(attr); //初始化属性 if (result ! 0) { cerr Error: pthread_attr_init failed: strerror(result) endl; return 0; } //设置分离状态 PTHREAD_CREATE_JOINABLE 或 PTHREAD_CREATE_DETACHED result pthread_attr_setdetachstate(attr, PTHREAD_CREATE_JOINABLE); if (result 0) { cout 设置线程为可连接状态(JOINABLE) endl; } // 设置堆栈大小256KB size_t stacksize 256 * 1024; // 256KB result pthread_attr_setstacksize(attr, stacksize); if (result 0) { size_t actual_stacksize; pthread_attr_getstacksize(attr, actual_stacksize); cout 设置堆栈大小: actual_stacksize bytes endl; } // 设置调度策略 普通应用用 SCHED_OTHER分时调度 result pthread_attr_setschedpolicy(attr, SCHED_OTHER); if (result 0) { cout 设置调度策略: SCHED_OTHER endl; } // 设置继承调度属性使用显式设置而非继承 result pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED); if (result 0) { cout 设置显式调度继承 endl; } //设置竞争范围Linux只支持系统级 Linux只支持 PTHREAD_SCOPE_SYSTEM result pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM); if (result 0) { cout 设置竞争范围: PTHREAD_SCOPE_SYSTEM endl; } // 创建新线程 // thread: 用于存储新线程的标识符 // NULL: 线程属性使用默认属性 // PrintThread: 线程函数指针新线程执行的函数 // (void *)param: 传递给线程函数的参数将long转换为void* result pthread_create(thread, attr, PrintThread, (void *)param); // 检查线程创建是否成功 if (result) // rc ! 0 表示创建失败 { // pthread_create返回错误码非零 // 通常应该处理错误这里直接返回 return 0; } result pthread_attr_destroy(attr); // 主线程继续执行自己的工作与子线程并发执行 for(int i 0; i 5; i){ cout Main thread i endl; // 主线程输出 sleep(2); // 休眠2秒子线程休眠1秒所以子线程输出更频繁 } pthread_join(thread, NULL); return 0; }outmain thread pid6255 main Self: id139668265477952 设置线程为可连接状态(JOINABLE) 设置堆栈大小: 262144 bytes 设置调度策略: SCHED_OTHER 设置显式调度继承 设置竞争范围: PTHREAD_SCOPE_SYSTEM Main thread 0 ChildThread: pid6255 ChildSelf: id139668265473792调用普通函数pthread_create接收的是函数指针,传入普通函数会报错参数类型错误必须接收void * ( * )(void * )采用外面线程包装函数error: invalid conversion from ‘void (*)()’ to ‘void* (*)(void*)’ [-fpermissive] rc pthread_create(thread, attr, PrintThread_1, NULL);void PrintThread_1() { for(int i 0; i 100; i){ cout i endl; sleep(1); } return; } void* thread_wrapper(void* arg) { (void)arg; // 忽略参数防止编译器警告 // 调用真正的无参数函数 PrintThread_1(); return NULL; // 线程返回值 } int result pthread_create(thread, attr, thread_wrapper, NULL);调用静态函数static void* PrintThread_2(void* arg) { (void)arg; for(int i 0; i 100; i){ cout i endl; sleep(1); } return NULL; } int result pthread_create(thread, attr, PrintThread_2, (void*)param);调用 类静态函数#include pthread.h #include iostream #include unistd.h using namespace std; class MyClass { public: // 静态成员函数 - 可以作为线程函数 static void* PrintThread_3(void* arg) { cout Static member function called endl; for(int i 0; i 10; i){ cout fun: i endl; sleep(1); } cout Static member function finished endl; return nullptr; } }; int main() { pthread_t thread; int param 42; // 直接调用类的静态成员函数 //pthread_create(thread, NULL, MyClass::PrintThread_3,param); // 通过类名调用静态函数 pthread_create(thread, NULL, MyClass::PrintThread_3, param); for(int i 0; i 10; i){ cout main: i endl; sleep(1); } pthread_join(thread, nullptr); cout Main: Thread completed endl; return 0; }