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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux——线程使用及互斥量

發(fā)布時(shí)間:2025/3/11 linux 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux——线程使用及互斥量 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

線程的基本操作

概念
線程是程序中的一個(gè)執(zhí)行路線。每個(gè)程序當(dāng)中至少有一個(gè)線程。
程序在執(zhí)行的過程中是逐條執(zhí)行的,按照代碼的邏輯一次向下執(zhí)行,所以無法同時(shí)完成兩條指令,故而引進(jìn)了線程,舉個(gè)很簡(jiǎn)單的例子,如果同時(shí)進(jìn)行兩個(gè)死循環(huán),用單線程的話只能進(jìn)行一個(gè)死循環(huán),另一個(gè)死循環(huán)永遠(yuǎn)也不會(huì)執(zhí)行,故而用多線程就可以解決這個(gè)問題。在學(xué)習(xí)網(wǎng)絡(luò)cs模型時(shí)更能體現(xiàn)線程的作用,因?yàn)槟阈枰诎l(fā)送數(shù)據(jù)的同時(shí)接收數(shù)據(jù)。

創(chuàng)建線程

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);參數(shù)thread:返回線程IDattr:設(shè)置線程的屬性,attr為NULL表示使用默認(rèn)屬性start_routine:是個(gè)函數(shù)地址,線程啟動(dòng)后要執(zhí)行的函數(shù)arg:傳給線程啟動(dòng)函數(shù)的參數(shù)返回值:成功返回0;失敗返回錯(cuò)誤碼

獲取線程ID

pthread_t pthread_self(void)返回值返回調(diào)用該函數(shù)的線程的ID

線程終止

void pthread_exit(void *value_ptr); 參數(shù)value_ptr:value_ptr不要指向一個(gè)局部變量。 該函數(shù)無返回值,跟進(jìn)程一樣,線程結(jié)束的時(shí)候無法返回到它的調(diào)用者(自身)int pthread_cancel(pthread_t thread); 參數(shù)thread:線程ID 返回值:成功返回0;失敗返回錯(cuò)誤碼

線程等待

int pthread_join(pthread_t thread, void **value_ptr); 參數(shù)thread:線程IDvalue_ptr:它指向一個(gè)指針,后者指向線程的返回值 返回值:成功返回0;失敗返回錯(cuò)誤碼

為何要線程等待?線程退出時(shí),其占有的空間資源并不會(huì)釋放掉,在次創(chuàng)建一個(gè)線程時(shí)該空間資源并不會(huì)被再次利用,也就是說會(huì)造成內(nèi)存泄漏,故而需要線程等待。其中線程等待函數(shù)中的參數(shù)value_ptr指向線程IDthread的線程返回值。如果thread線程被別的線程調(diào)用pthread_ cancel異常終掉,value_ ptr所指向的單元里存放的是常數(shù)PTHREAD_ CANCELED;如果thread線程是自己調(diào)用pthread_exit終止的,value_ptr所指向的單元存放的是傳給pthread_exit的參數(shù)。

線程分離

int pthread_detach(pthread_t thread); 參數(shù)thread:線程ID 返回值:成功返回0,錯(cuò)誤返回錯(cuò)誤號(hào)

線程分離與線程等待很相似,他們都能釋放掉已結(jié)束線程占用的空間資源,但線程分離不關(guān)心線程退出的返回值,只要線程退出,就自動(dòng)釋放線程資源。

編譯指令

gcc 123.c -o out -lpthread 注:編譯多線程的程序一定要加上 -lpthread

示例:

#include<pthread.h> #include<stdio.h> #include<unistd.h> void *fun(void *num) {int i=0;for(;i<30;i++){printf("a");if(i==25){pthread_exit(NULL);//輸出25個(gè)a后線程終止}usleep(1);//延時(shí)1us} }int main() {pthread_t ptid;if(pthread_create(&ptid,NULL,fun,NULL)!=0)//創(chuàng)建線程{return 0;}int i=0;for(;i<10;i++){if(i%2==0){printf("b");}usleep(2);//延時(shí)2us}printf("\n");pthread_join(ptid,NULL);線程等待return 0; }

結(jié)果

主線程在執(zhí)行5個(gè)b后,輸出結(jié)束,此時(shí)等待子線程結(jié)束,即第二行結(jié)果顯示,至于第一行為什么a、b都有輸出,是因?yàn)榫€程在執(zhí)行時(shí)是同時(shí)進(jìn)行的,主線程輸出一個(gè)b后睡眠2us,在這段時(shí)間子線程開始輸出a,因?yàn)樽泳€程也有1us睡眠,限制其執(zhí)行速度,當(dāng)主線程的2us時(shí)間到后,又開始主線程輸出b。

線程互斥

我們先看看幾個(gè)概念:

臨界資源:多線程執(zhí)行流共享的資源就叫做臨界資源 臨界區(qū):每個(gè)線程內(nèi)部,訪問臨界資源的代碼,就叫做臨界區(qū) 互斥:任何時(shí)刻,互斥保證有且只有一個(gè)執(zhí)行流進(jìn)入臨界區(qū),訪問臨界資源,通常對(duì)臨界資源起保護(hù)作 用 原子性:不會(huì)被任何調(diào)度機(jī)制打斷的操作,該操作只有兩態(tài),要么完成,要么未完成

那到底什么是線程互斥呢?不要著急,我們先看看下面這個(gè)搶票的例子:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <sched.h>int ticket = 100;//共有100張票void *route(void *arg) {char *id=(char *)arg;while(1){if(ticket>0){usleep(1000);printf("%s sells ticket:%d\n",id,ticket);ticket--;//搶到票就減1}else{break; }} } int main() {pthread_t t1,t2,t3,t4;pthread_create(&t1,NULL,route,(void *)"thread 1");pthread_create(&t2,NULL,route,(void *)"thread 2");pthread_create(&t3,NULL,route,(void *)"thread 3");pthread_create(&t4,NULL,route,(void *)"thread 4");pthread_join(t1,NULL);pthread_join(t2,NULL);pthread_join(t3,NULL);pthread_join(t4,NULL);return 0;}

結(jié)果

結(jié)果讓人感到意外,怎么會(huì)有負(fù)數(shù)呢?因?yàn)榫€程是同時(shí)進(jìn)行的,當(dāng)進(jìn)行到票數(shù)為1的時(shí)候,此時(shí)部分線程已經(jīng)經(jīng)過了**if(ticket>0)**的判斷,其中有一個(gè)線程的執(zhí)行速度比較快,他搶先拿到了最后的一張票,此時(shí)票數(shù)為0,因?yàn)榇藭r(shí)并不止這一個(gè)線程經(jīng)過了判斷,他們也能強(qiáng)到一張票,故而出現(xiàn)負(fù)數(shù)。原理圖如下:

為避免上述現(xiàn)象的出現(xiàn),引進(jìn)了互斥量mutex

互斥量初始化

靜態(tài)分配 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;動(dòng)態(tài)分配 int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);參數(shù):mutex:要初始化的互斥量attr:NULL

互斥量加鎖與解鎖

加鎖: int pthread_mutex_lock(pthread_mutex_t *mutex);解鎖: int pthread_mutex_unlock(pthread_mutex_t *mutex); 注:加鎖后一定要記得解鎖二者的參數(shù)相同,都是指初始化后的互斥量

互斥量銷毀

int pthread_mutex_destroy(pthread_mutex_t *mutex); 參數(shù):需要銷毀的互斥量 注:靜態(tài)分配的互斥量不需要銷毀,已經(jīng)枷鎖的互斥量不能銷毀

使用方法

  • 在使用前先初始化
  • 訪問臨界資源前加鎖
  • 訪問臨界資源后解鎖
  • 互斥量使用結(jié)束后銷毀
  • 改進(jìn)后代碼

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <sched.h>int ticket = 100;//票 pthread_mutex_t mutex;//定義互斥量void *route(void *arg) {char *id=(char *)arg;while(1){pthread_mutex_lock(&mutex);//加鎖if(ticket>0){printf("%s sells ticket:%d\n",id,ticket);ticket--;pthread_mutex_unlock(&mutex);//解鎖}else{pthread_mutex_unlock(&mutex);//解鎖break;}usleep(2);} } int main() {pthread_t t1,t2,t3,t4;pthread_mutex_init(&mutex,NULL);//初始化互斥量pthread_create(&t1,NULL,route,(void *)"thread 1");pthread_create(&t2,NULL,route,(void *)"thread 2");pthread_create(&t3,NULL,route,(void *)"thread 3");pthread_create(&t4,NULL,route,(void *)"thread 4");pthread_join(t1,NULL);pthread_join(t2,NULL);pthread_join(t3,NULL);pthread_join(t4,NULL);pthread_mutex_destroy(&mutex);//互斥量銷毀return 0;}

    結(jié)果

    總結(jié)

    以上是生活随笔為你收集整理的Linux——线程使用及互斥量的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。