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

浙公網安備 33010602011771號