C++线程
进程以CPU为运行单位,多个CPU可以实现进程并行,单个CPU可以实现进程并发(进程调度)
线程以CPU的核心为运行单位,多个CPU内核可以实现线程并行,单个内核可以实现线程并发(线程调度)
1、创建和结束一个线程
#include <iostream> #include <pthread.h> /// @brief 创建一个线程 /// @param 线程标识符指针 /// @param 线程属性对象 /// @param 线程运行函数指针 /// @param 线程运行函数参数 /// @return 创建线程成功时,函数返回 0,若返回值不为 0 则说明创建线程失败。 // int pthread_create(pthread_t *, const pthread_attr_t *, void *(__PTW32_CDECL *)(void *), void *); // 线程运行函数 void *pthreadFun(void *arg) { cout << "num is " << *(int *)arg << endl; // 终止线程 pthread_exit(nullptr); } int main(int argc, char **argv) { // 线程标识符 pthread_t tid[5] = {0}; for (int i = 0; i < THREAD_NUM; i++)
{ pthread_create(&tid[i], nullptr, pthreadFun, (void *)&i); // 等待线程启动 sleep(1); } return 0; }
编译运行:
PS F:\tinyxml_2_6_2\tinyxml> g++ .\main.cpp -o pmain -lpthread
PS F:\tinyxml_2_6_2\tinyxml> .\pmain.exe
2、连接和分离线程
连接线程:将子线程连接入主线程,主线程阻塞等待子线程运行结束。然后回收子线程资源。
#include <csignal> #include <cstdlib> #include <iostream> #include <pthread.h> #include <unistd.h> using namespace std; #define THREAD_NUM 5 void signalHander(int sigNum) { cout << "signum :" << signal << endl; } /// @brief 创建一个线程 /// @param 线程标识符指针 /// @param 线程属性对象 /// @param 线程运行函数指针 /// @param 线程运行函数参数 /// @return 创建线程成功时,函数返回 0,若返回值不为 0 则说明创建线程失败。 // int pthread_create(pthread_t *, const pthread_attr_t *, void *(__PTW32_CDECL *)(void *), void *); // pthread_attr_init(pthread_attr_t *); /// @brief 初始化线程属性组 /// @param 线程标识符 pthread_attr_destroy(pthread_attr_t *); /// @brief 连接线程,将主线程合入子线程,主线程等待子线程结束然后再向下执行 /// @param 线程标识符 /// @param 子线程返回值 pthread_join(pthread_t, void **); /// @brief 分离线程 /// @param 线程标识符 pthread_detach(pthread_t); // 线程运行函数 void *pthreadFun(void *arg) { cout << "num is " << *(int *)arg << endl; // 终止线程 pthread_exit(nullptr); } int main(int argc, char **argv) { // 线程标识符 pthread_t tid[5] = {0}; // 线程属性组 pthread_attr_t pat; pthread_attr_init(&pat); pthread_attr_setdetachstate(&pat, PTHREAD_CREATE_JOINABLE); for (int i = 0; i < 5; i++) { pthread_create(&tid[i], &pat, pthreadFun, (void *)&i); // 等待一个线程启动再启动下一个线程 sleep(1); } void *statRet = nullptr; for (int i = 0; i < 5; i++) { pthread_join(tid[i], &statRet); cout << "statRet :" << statRet << endl; } pthread_attr_destroy(&pat); return 0; }
编译运行:
PS F:\tinyxml_2_6_2\tinyxml> g++ .\main.cpp -o pmain -lpthread
PS F:\tinyxml_2_6_2\tinyxml> .\pmain.exe
分离线程:子线程与主线程分离,子线程结束后自动回收资源。
/// @brief 创建一个线程 /// @param 线程标识符指针 /// @param 线程属性对象 /// @param 线程运行函数指针 /// @param 线程运行函数参数 /// @return 创建线程成功时,函数返回 0,若返回值不为 0 则说明创建线程失败。 int pthread_create(pthread_t *, const pthread_attr_t *, void *(__PTW32_CDECL *)(void *), void *); /// @brief 初始化线程属性结构体 /// @param 线程属性结果体指针 pthread_attr_init(pthread_attr_t *); /// @brief 初始化线程属性组 /// @param 线程标识符 pthread_attr_destroy(pthread_attr_t *); /// @brief 连接线程,将主线程合入子线程,主线程等待子线程结束然后再向下执行 /// @param 线程标识符 /// @param 子线程返回值 pthread_join(pthread_t, void **); /// @brief 分离线程 /// @param 线程标识符 pthread_detach(pthread_t); // 线程运行函数 void *pthreadFun(void *arg) { cout << "num is " << *(int *)arg << endl; // 终止线程 pthread_exit(nullptr); } int main(int argc, char **argv) { // 线程标识符 pthread_t tid[5] = {0}; // 线程属性组 pthread_attr_t pat; pthread_attr_init(&pat); pthread_attr_setdetachstate(&pat, PTHREAD_CREATE_DETACHED);
for (int i = 0; i < 5; i++) { pthread_create(&tid[i], &pat, pthreadFun, (void *)&i); // 等待一个线程启动再启动下一个线程 sleep(1); } void *statRet = nullptr; for (int i = 0; i < 5; i++) { pthread_detach(tid[i]); cout << "statRet :" << statRet << endl; } pthread_attr_destroy(&pat); return 0; }
编译运行:
PS F:\tinyxml_2_6_2\tinyxml> g++ .\main.cpp -o pmain -lpthread
PS F:\tinyxml_2_6_2\tinyxml> .\pmain.exe
3、线程间的信号量
(信号是不同于信号量的吧哈哈哈哈哈,刚开始把信号当成信号量调了好半天程序,蠢死我了)
#include <iostream> #include <pthread.h> #include <semaphore.h> using namespace std; /// @brief 初始化未命名一个信号量 /// @param sem 一个信号量的指针 /// @param pshared 标志信号量是进程共享还是线程共享,为0则是线程间共享,不为0则是进程间共享 /// @param value 设置信号量的初始值 /// @return 成功返回0,失败返回-1 int sem_init(sem_t *sem, int pshared, unsigned int value); /// @brief 销毁一个未命名信号量 /// @param sem 一个信号量的指针 /// @return 成功返回0,失败返回-1 int sem_destroy(sem_t *sem); /// @brief 锁定、递减信号量 /// @param sem 要锁定的信号量的指针 /// @return 成功返回0,失败返回-1 int sem_wait(sem_t *sem); /// @brief 解锁信号量 /// @param sem 要解锁的信号量的指针 /// @return 成功返回0,失败返回-1 int sem_post(sem_t *sem); void *pthread_1(void *arg); void *pthread_2(void *arg); sem_t sem1; sem_t sem2; int main(int argc, char **argv) { int ret = 0; if (0 != sem_init(&sem1, 0, 1)) cerr << "sem_init" << endl; if (0 != sem_init(&sem2, 0, 1)) cerr << "sem_init" << endl; pthread_t tid[2] = {0}; pthread_attr_t pat_1; pthread_attr_t pat_2; pthread_attr_init(&pat_1); pthread_attr_setdetachstate(&pat_1, PTHREAD_CREATE_JOINABLE); pthread_attr_init(&pat_2); pthread_attr_setdetachstate(&pat_2, PTHREAD_CREATE_JOINABLE); pthread_create(&tid[0], &pat_1, pthread_1, nullptr); pthread_create(&tid[1], &pat_2, pthread_2, nullptr); void *statRet = nullptr; pthread_join(tid[0], &statRet); pthread_join(tid[1], &statRet); pthread_attr_destroy(&pat_1); pthread_attr_destroy(&pat_2); pthread_exit(nullptr); if (ret != sem_destroy(&sem1)) cerr << "sem1_destroy" << endl; if (ret != sem_destroy(&sem2)) cerr << "sem2_destroy" << endl; return 0; } void *pthread_1(void *arg) { while (1) { if (0 != sem_wait(&sem1)) cerr << "sem1_wait" << endl; cout << "wait sem1 OK" << endl; sleep(1); if (0 != sem_post(&sem2)) cerr << "sem2_post" << endl; cout << "post sem2 OK" << endl; sleep(1); } pthread_exit(nullptr); } void *pthread_2(void *arg) { while (1) { if (0 != sem_wait(&sem2)) cerr << "sem2_wait" << endl; cout << "wait sem2 OK" << endl; sleep(1); if (0 != sem_post(&sem1)) cerr << "sem1_post" << endl; cout << "post sem1 OK" << endl; sleep(1); } pthread_exit(nullptr); }
编译运行:
PS F:\tinyxml_2_6_2\tinyxml> g++ .\main.cpp -o pmain -lpthread
PS F:\tinyxml_2_6_2\tinyxml> .\pmain.exe