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

歡迎訪問 生活随笔!

生活随笔

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

linux

Linux多线程基础总结

發(fā)布時間:2023/12/31 linux 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux多线程基础总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、線程參數(shù)傳遞

線程傳遞的參數(shù)類型為void*,傳遞方式有值傳遞、指針傳遞、引用傳遞

  • 值傳遞:拷貝一份值給新的線程,多線程間不共享

  • 址傳遞(指針傳遞):

    • 連續(xù)創(chuàng)建多個線程中如果傳入的是同一變量地址,多線程共享這變量,由于哪個線程先運行是不確定的,變量的值是不可控的,并且會造成共享資源競爭問題,因為修改變量的值不是原子操作
    • 如果主線程先結(jié)束,其內(nèi)存空間會被釋放,子進(jìn)程中的指針就成了野指針,可想而知,繼續(xù)操作這塊內(nèi)存會造成意想不到的后果。
      結(jié)果方案:定義的變量使用堆內(nèi)存分配,可以避免棧內(nèi)存釋放,也可以使用全局變量
  • 二、線程分離

    線程分離后,線程退出自動釋放全部資源:pthread_detach()

    三、線程資源的回收

    非分離狀態(tài)的線程才可以被join回收資源

  • 阻塞回收:pthread_join()

  • 非阻塞回收:pthread_tryjoin_np()

  • 限時阻塞回收:pthread_timedjoin_np()

  • 四、線程清理函數(shù)

    線程終止的時候,可以調(diào)用清理函數(shù)釋放資源,入棧和出棧函數(shù)必須成對的出現(xiàn)

  • 清理函數(shù)入棧:pthread_cleanup_push()

  • 清理函數(shù)出棧:pthread_cleanup_pop()(0:出棧不執(zhí)行 非零:出棧并執(zhí)行)

  • 五、線程取消

  • 線程在運行過程中可以調(diào)用被取消:pthread_cancel()

  • 線程被取消后,join返回值為PTHREAD_CANCELED 即 -1

  • 設(shè)置線程的取消狀態(tài):pthread_setcancelstate()
    宏:PTHREAD_CANCEL_ASYNCHRONOUS: 立即取消
    宏:PTHREAD_CANCEL_DEFERRED: 到達(dá)取消點(例如sleep())才取消
    設(shè)置線程的取消點:pthread_testcancel()

  • 六、線程與信號

  • 向指定線程發(fā)送信號:pthread_kill()
  • 信號屏蔽:進(jìn)程:sigpromask() 線程:pthread_sigmask()
  • 阻塞等待信號:sigwait()、sigwaitinfo()、sigtimedwait()
  • 在多線程中,外部向進(jìn)程發(fā)送信號(ctl+c)不會中斷系統(tǒng)調(diào)用(sleep())
  • 在多線程中,信號的處理是所有線程共享的(即信號注冊在任一線程中注冊都可以)
  • 進(jìn)程中的信號可以送達(dá)單個線程,會中斷系統(tǒng)調(diào)用
  • 如果某個線程因為信號(SIGTERM默認(rèn)處理)而終止,整個進(jìn)程將終止
  • 七、線程安全

  • 多個線程訪問共享資源(全局和靜態(tài)變量)的時候會沖突
    例:定義全局變量int a=0; 線程1和線程2同時:循環(huán)執(zhí)行 a++ 一萬次 得到a的值小于2萬,a并不會自動到兩萬

  • 三個概念:原子性、可見性、順序性

    • 原子性
      一個操作(有可能包含有多個子操作)要么全部執(zhí)行(生效)要么全部都不執(zhí)行(都不生效)
      CPU執(zhí)行指令:讀取指令、讀取內(nèi)存、執(zhí)行指令、寫回內(nèi)存
      例(非原子性):第一不讀取指令:i++ 第二步:從內(nèi)存中讀取i的值 第三步:把i+1 第四步:把結(jié)果寫回內(nèi)存
    • 可見性
      當(dāng)多個線程并發(fā)訪問共享變量時,一個線程對共享變量的修改,其它線程能夠立即看到。
      CPU有高速緩存。每個線程讀取共享變量時,會將該變量從內(nèi)存加載到CPU的緩存中,修改該變量后,CPU會立即更新緩存,但不一定會立即將它寫回內(nèi)存。此時其它線程訪問該變量,從內(nèi)存中讀到的是舊數(shù)據(jù),而非第一個線程更新后的數(shù)據(jù)。

    • 順序性
      程序執(zhí)行的順序按照代碼的先后順序執(zhí)行。
      CPU為了提高程序整體的執(zhí)行效率,可能會對代碼進(jìn)行優(yōu)化,按照更高效的順序執(zhí)行代碼。
      CPU雖然并不保證完全按照代碼順序執(zhí)行,但它會保證程序最終的執(zhí)行結(jié)果和代碼順序執(zhí)行時的結(jié)果一致。
      例:int a = 1; a = 2; a = 3; 編譯器對代碼優(yōu)化為int a = 3;

  • volatile關(guān)鍵字:保證可見性和禁止代碼優(yōu)化,但不是原子操作

  • 解決線程安全問題:原子操作(c++原子類)、和線程同步(鎖)
    原子操作:本質(zhì)是總線鎖

  • 八、線程同步

    1. 互斥鎖

    等待鎖的時候,線程會休眠,不會消耗CPU,適合等待時間可能很長的場景

    聲明鎖

    pthread_mutex_t mutex;
    • 普通鎖: PTHREAD_MUTEX_TIMED_NP
      當(dāng)一個線程加鎖以后,其余請求鎖的線程將形成一個等待隊列,并在解鎖后按優(yōu)先級獲得鎖。
      這種鎖策略保證了資源分配的公平性。

    • 嵌套鎖:PTHREAD_MUTEX_RECURSIVE_NP
      允許同一個線程對同一個鎖成功獲得多次,并通過多次unlock解鎖。
      如果是不同線程請求,則在加鎖線程解鎖時重新競爭。

    • 適應(yīng)鎖:PTHREAD_MUTEX_ADAPTIVE_NP
      解鎖后,請求鎖的線程重新競爭。

    int pthread_mutex_init(); //初始化鎖,也可定義時直接使用宏初始化如上int pthread_mutex_lock(); //等待并加鎖int pthread_mutex_trylock(); //嘗試加鎖,不等待int pthread_mutex_timedlock();//帶超時機(jī)制的加鎖int pthread_mutex_unlock() //解鎖int pthread_mutex_destroy(); //銷毀鎖

    2. 自旋鎖

    循環(huán)的加測鎖是否可用,會消耗CPU,適合等待時間很短的場景

    pthread_spinlock_t mutex; //聲明鎖 int pthread_spin_init(); //初始化鎖 int pthread_spin_lock(); //等待并加鎖 int pthread_spin_trylock(); //嘗試加鎖,不等待 int pthread_spin_unlock(); //解鎖 int pthread_spin_destroy(); //銷毀鎖

    4. 讀寫鎖

    讀時共享,寫時單獨,適用于讀的次數(shù)遠(yuǎn)大于寫的場景

    • 定義鎖

      pthread_rwlock_t mutex; //聲明鎖PTHREAD_RWLOCK_INITIALIZER //使用宏初始化鎖int pthread_rwlock_init(); //初始化鎖int pthread_rwlock_destroy(); //銷毀鎖
    • 鎖屬性

      int pthread_rwlockattr_getpshared();//獲取讀寫鎖屬性 int pthread_rwlockattr_setpshared();//設(shè)置讀寫鎖屬性 PTHREAD_PROXESS_PRIVATE(單個線程私有) PTHREAD_PROCESS_SHARED(多線程共享)
    • 讀鎖

      int pthread_rwlock_rdlock(); //阻塞獲取讀鎖 int pthread_rwlock_tryrdlock(); //嘗試獲取讀鎖,不阻塞 int pthread_rwlock_timedrdlock(); //獲取讀鎖,帶超時機(jī)制
    • 寫鎖

      int pthread_rwlock_wrlock(); //阻塞獲取寫鎖 int pthread_rwlock_trywrlock(); //嘗試獲取寫鎖,不阻塞 int pthread_rwlock_timedwrlock(); //獲取寫鎖,帶超時機(jī)制

    注意:只有在不加鎖時,才能獲取到寫鎖。linux系統(tǒng)優(yōu)先考慮獲取讀鎖,獲取寫鎖的線程需要等待所有讀鎖釋放才能獲得到鎖

    九、條件變量

    pthread_cond_t cond; //聲明條件變量 PTHREAD_COND_INITIALIZER; //使用宏初始化條件變量 int pthread_cond_init(); //初始化條件變量 int pthread_cond_destroy(); //銷毀條件變量int pthread_cond_wait(); //等待被喚醒進(jìn)行加鎖 int pthread_cond_timedwait();//等待被喚醒進(jìn)行加鎖,帶超時機(jī)制int pthread_cond_signal(); //喚醒至少一個等待中的線程 int pthread_cond_broadcast();//喚醒全部等待中的線程int pthread_condattr_getpshared();//獲取共享屬性 int pthread_condattr_setpshared();//設(shè)置共享屬性(單個線程私有、多線程共享)

    十、信號量

    多進(jìn)程的信號量可以用在多線程中,而多線程的信號量只能用于多線程中,多線程的信號量使用比較簡單

    sem_t *sem; //聲明信號量 int sem_init(); //初始化信號量 int sem_destroy();//銷毀信號量int sem_wait(sem_t *sem); //信號量的P操作 int sem_trywait(sem_t *sem);//信號量的P操作,不阻塞 int sem_timedwait(); //信號量的P操作,帶超時機(jī)制 int sem_post(sem_t *sem); //信號量的V操作 int sem_getvalue(); //獲取信號量的值

    注意:以上幾種同步機(jī)制都能形成等待隊列,但是不是絕對公平的,當(dāng)前線程的cpu時間片還未使用完,獲取到鎖的概率會很大

    十一、生產(chǎn)者消費者模型

  • 互斥鎖+條件變量實現(xiàn)
  • 信號量實現(xiàn)
  • 十二、保證多線程程序的穩(wěn)定性

  • 主進(jìn)程只用與監(jiān)控和調(diào)度
  • 程序的功能由子線程實現(xiàn),把心跳寫入全局變量
  • 如果心跳超時,取消子線程再重新啟動
  • 十三、多線程實現(xiàn)異步通訊

    主線程創(chuàng)建socket連接,一個子線程負(fù)責(zé)發(fā)送,另一個子線程負(fù)責(zé)接收

    總結(jié)

    以上是生活随笔為你收集整理的Linux多线程基础总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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