日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux多线程实践(2) --线程基本API

發布時間:2025/3/17 linux 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux多线程实践(2) --线程基本API 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

POSIX線程庫

? 與線程有關的函數構成了一個完整的系列,絕大多數函數的名字都是以“pthread_”開頭,要使用這些函數庫,要通過引入頭文<pthread.h>,而且鏈接這些線程函數庫時要使用編譯器命令的“-lpthread”選項[Ubuntu系列系統需要添加的是”-pthread”選項而不是”-lpthread”,如Ubuntu?14.04版本,深度Ubuntu等]

?

1.pthread_create

int pthread_create(pthread_t *restrict thread,const pthread_attr_t *restrict attr,void *(*start_routine)(void*), void *restrict arg);

創建一個新的線程

參數

? thread:線程ID

??attr:設置線程的屬性,一般設置為NULL表示使用默認屬性

??start_routine:是個函數地址,線程啟動后要執行的函數

??arg:傳給線程啟動函數的參數

返回值:成功返回0;失敗返回錯誤碼;

?

附-Posix錯誤檢查

??UNIX傳統的函數:成功返回0,失敗返回-1,并且對設置全局變量errno以指定錯誤類型。然而pthreads函數出錯時不會設置全局變量errno(而其他的大部分POSIX函數會設置errno)。而是將錯誤代碼通過返回值返回;

??pthreads同樣也提供了線程內的errno變量,對于每一個線程,?都有一個errno的值,?以支持其它使用errno的代碼。對于pthreads函數的錯誤,建議通過返回值進行判定,因為讀取返回值要比讀取線程內的errno變量的開銷更小!

/** 實踐: 新的錯誤檢查與錯誤退出函數 **/ inline void err_check(const std::string &msg, int retno) {if (retno != 0)err_exit(msg, retno); } inline void err_exit(const std::string &msg, int retno) {std::cerr << msg << ": " << strerror(retno) << endl;exit(EXIT_FAILURE); }

2.pthread_exit

void pthread_exit(void *value_ptr);

線程終止

? value_ptr:指向該線程的返回值;注意:value_ptr不能指向一個局部變量

?

3.pthread_join

int pthread_join(pthread_t thread, void **value_ptr);

等待線程結束

??value_ptr:它指向一個指針,后者指向線程的返回值(用戶獲取線程的返回值)

/** 示例: 等待線程退出 **/ void *thread_rotine(void *args) {for (int i = 0; i < 10; ++i){printf("B");fflush(stdout);usleep(20);}pthread_exit(NULL); }int main() {pthread_t thread;int ret = pthread_create(&thread, NULL, thread_rotine, NULL);err_check("pthread_create", ret);for (int i = 0; i < 10; ++i){printf("A");fflush(stdout);usleep(20);}ret = pthread_join(thread, NULL);err_check("pthread_join", ret);putchar('\n');return 0; }

4.pthread_self

pthread_t pthread_self(void);

返回線程ID

/** 示例:主控線程與子線程傳遞數據 **/ typedef struct _Student {char name[20];unsigned int age; } Student;void *threadFunction(void *args) {cout << "In Thread: " << pthread_self() << endl;Student tmp = *(Student *)(args);cout << "Name: " << tmp.name << endl;cout << "Age: " << tmp.age << endl;pthread_exit(NULL); }int main() {Student student = {"xiaofang",22};pthread_t thread;//啟動創建并啟動線程pthread_create(&thread,NULL,threadFunction,&student);//等待線程結束pthread_join(thread,NULL);return 0; }

5.pthread_cancel

int pthread_cancel(pthread_t thread);

取消一個執行中的線程


6.pthread_detach

int pthread_detach(pthread_t thread);

??將一個線程分離-如果在新創建的線程結束時主線程沒有結束同時也沒有調用pthread_join,則會產生僵線程,次問題可以通過設置線程為分離的(detach)來解決;

?

總結:進程 VS.?線程

進程(pid_t)

線程(pthread_t)

Fork

Pthread_create

Waitpit

Pthread_join/Pthread_detach

Kill

Pthread_cancel

Pid

Pthead_self

Exit/return

Pthread_exit/return

僵尸進程(沒有調用wait/waitpid等函數)

僵尸線程(沒有調用pthread_join/pthread_detach)

/** 將并發echo server改造成多線程形式 注意線程競速問題的解決 **/ void echo_server(int clientSocket); void *thread_routine(void *arg); int main() {int sockfd = socket(AF_INET,SOCK_STREAM,0);if (sockfd == -1)err_exit("socket error");int optval = 1;if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)) == -1)err_exit("setsockopt error");struct sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(8002);serverAddr.sin_addr.s_addr = INADDR_ANY; //綁定本機的任意一個IP地址if (bind(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == -1)err_exit("bind error");if (listen(sockfd,SOMAXCONN) == -1)err_exit("listen error");while (true){int peerSockfd = accept(sockfd, NULL, NULL);if (peerSockfd == -1)err_exit("accept error");pthread_t tid;/**注意: 下面這種用法可能會產生"競速問題"當另一個連接快讀快速到達, peerSockfd的內容更改,新創建的線程尚未將該值取走時,線程讀取的就不是我們想讓線程讀取的值了int ret = pthread_create(&tid, NULL, thread_routine, (void *)&peerSockfd);**///解決方案: 為每一個鏈接創建一塊內存int *p = new int(peerSockfd);int ret = pthread_create(&tid, NULL, thread_routine, p);if (ret != 0)err_thread("pthread_create error", ret);}close(sockfd); } void *thread_routine(void *args) {//將線程設置分離狀態, 避免出現僵尸線程pthread_detach(pthread_self());int peerSockfd = *(int *)args;//將值取到之后就將這塊內存釋放掉delete (int *)args;echo_server(peerSockfd);cout << "thread " << pthread_self() << " exiting ..." << endl;pthread_exit(NULL); } void echo_server(int clientSocket) {char buf[BUFSIZ] = {0};int readBytes;while ((readBytes = read(clientSocket, buf, sizeof(buf))) >= 0){if (readBytes == 0){cerr << "client connect closed" << endl;break;}if (write(clientSocket, buf, readBytes) == -1){cerr << "server thread write error" << endl;break;}cout << buf;bzero(buf, sizeof(buf));} }

其完整源代碼:download.csdn.net/detail/hanqing280441589/8440763


新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!

總結

以上是生活随笔為你收集整理的Linux多线程实践(2) --线程基本API的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。