【2016/3】多線程編程 線程同步技術 線程鎖 用戶校驗

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/hsgwpj/article/details/50933879

線程的一些概念:

   父線程結束 子線程立馬同歸於盡

— 子線程受到進程級別的打擊 整個家族會瞬間爆炸
線程具有進程特性 也具有PID
— 線程有兩重身份: 1.線程身份 2.子進程身份
— 線程就是與親族之間共享資源的輕量級進程, 共享父進程的空間

子線程創建的新線程是它的兄弟: 他們共享空間,身份均等
— 但是會有一個本質上爲兄弟線程的父線程用來管理別的線程

   線程的棧是私有的

線程的優勢是快,輕量級, 它是高速進程

   線程是程序調度的基本單位, 進程是資源分配的基本單位(獨立的資源空間)

多線程是主進程中衍生的共享進程資源的線程的集合

線程的函數是庫函數,是在用戶空間運行

ps auxH 來查看線程
pstree -ap也可以查看線程
— 每個線程都具有其私有的PID 用大括號括起來的
線程的tid只在一個進程空間有效,離開進程空間就無效了
— 僅僅是用來標記子線程的信息,給予操作線程的機會
— tid纔是我們操作的對象

創建線程:

int pthread_create(pthread_t *tidp,const pthread_attr_t *attr, (void*)(*start_rtn)(void*),void *arg);
 tidp: 返回的tid值
 attr:線程的狀態 一般使用NULL來賦值
 start_rtn: 線程執行的函數 對函數的返回值與參數有要求
 arg: 函數傳入的參數

注意:

   線程只能調用 pthread_exit(NULL) 函數來退出, 如果調用exit則瞬間爆炸
   線程分離: pthread_detach(pthread_t thread);
   將分離的屬性與主線程切斷聯繫

在子線程結束後自動回收資源(*唯一的區別!)
— 與之相對的是線程回收程序:pthread_join(pthread_t thread, void *);
不能回收已經分離的回收程序, 這個程序就是給子線程收屍用的

pthread_equal():用來確認是不是給自己發, 防止發錯
pthread_cancel():取消線程,是等到合適的時機取消! (取消點)
— 系統函數就有取消點
pthread_testcancel(void) 人爲製造取消點 要加入到函數的重複路徑上!
— 分離的子線程也可以被取消

Tips: 迭代與遞歸的區別? **

 循環不一定能被遞歸替換 反而是可以: 遞歸調用會佔用棧空間,次數太多時會出現錯誤

pthread_setcanceltype(): 設置如何響應取消
pthread_setcancelstate(): 設置是否能被取消
pthread_sigmask()/kill(): 用法跟原來一樣

練習:

1.通過多線程來拷貝文件 實現多線程的CP
確定參數列表中每個文件的大小先, 然後再開始設計創建線程,並分配任務
把CP 的文件的信息保存再結構體中 然後再傳入結構體進行線程的拷貝
可以有上限和下限 然後通過合理規則決定線程數量

2.線程池!
       一次性創建很多線程,掛起等待命令的到來
       每次命令運行的時候,尋找一個池中閒置的線程
       運行傳入函數的命令
       運行完之後再回收

   int pthread_pool_create(int num_of_pthread);
   --- 線程要活着掛起!
   --- 記得設定線程MAX數量
   int pthread_pool_mission(void * (*fn)(void *arg), void *arg);
   --- 分配任務函數: 分配給線程池中某一個閒的函數
   --- 返回值是分配成功與否, no wait!
   int pthread_pool_end(void);
   --- 想象怎麼join掉所有的子進程! lwp?
   --- 用返回值告訴用戶成功與否!

線程屬性:

sysconf(): 獲取線程最大數量 return -1: 出錯/沒有限制
— 線程有棧的大小的上限
設置取消狀態是在線程開始運行之後設定的:
pthread_setcancelstate();
pthread_setcanceltypde();

初始化/銷燬結構體: pthread_attr_init()/destroy();
棧,棧地址、大小,棧警戒區,分離屬性(2個宏)
— 函數在書上或者 man -k pthread_attr

Tips: 並不建議使用線程屬性, 系統分配的一定是很好的

2016-1-23:

線程同步技術:

   1.線程鎖
   2.自旋鎖
   3.讀寫鎖
   4.條件變量

類似全局變量, 減少切換內存片段的代價
— 查找進線程的區別(Teacher Blog) 總結條數

線程鎖: pthread_mutex_t

   1.普通鎖: 加鎖一次解鎖一次                 |先等先得
   2.嵌套鎖: 可以重複加鎖,解鎖夠了纔開鎖      |自由競爭 (可互斥 可計數)
   3.糾錯鎖: 重複加鎖報錯,只能由本線程解鎖    |先等先得
   4.自適應鎖:加鎖一次 解鎖一次               |自由競爭

— 通過函數初始化與銷燬鎖:
靜態初始化: mutex = 宏值
動態初始化:

    pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t * attr);

— attr結構體設置

        pthread_mutexattr_init(); //初始化 
    pthread_mutexattr_settype();  //設置屬性 才能動態初始化

刪除鎖之前先鎖(失敗則掛起等待)後解鎖 確保沒有人正在使用這個鎖


           pthread_mutex_lock();        //加鎖 出錯就掛起
           pthread_mutex_trylock();     //加鎖 出錯就返回
           pthread_mutex_timedlock();   //加鎖 超時就返回
           pthread_mutex_unlock() ;     //解鎖

穿插加鎖是很危險的, 容易造成死鎖
在紅帽7.0的內核下 pthread庫的解鎖加鎖中改變了 :
掛起的時候發現被解鎖會慢一拍,會被剝奪使用CPU的能力
而正在使用鎖的人解鎖後繼續搶奪資源時會立刻搶到鎖
爲解決這個問題,讓使用鎖的人usleep(10)一下有利於公平競爭

自旋鎖:pthread_spinlock_t

   短程佔用高頻佔用式
   時刻等待着鎖的資源,不停地詢問是否鎖是空閒的
   對鎖等待時間短的時候才使用自旋鎖
   希望快速等待到資源才使用: 對CPU的佔用較高!

自旋鎖沒有種類:但是有是否線程間共享鎖的創建參數(PTHREAD_PORCESS_PRIVATE/SHARED)

       pthread_spin_lock/trylock/unlock()

讀寫鎖:pthread_rwlock_t

   讀多寫少的場景
   一讀多讀 一寫都禁 (爲了取得寫的權限 則不能有人正在讀 也不能有人繼續獲得寫權限)
   可以避免飢渴問題, 取決於互斥問題
   爲了保護讀寫操作

也有初始化的靜態宏值 在/usr/include/pthread.h中有定義 (有讀優先和寫優先類型)

   pthread_rwlock_init/destory/rdlock/wrlock/unlock/tryrdlock/trywrlock..

條件變量:pthread_cond_t

用於不知道何時釋放鎖的時候,處於盲等狀態,使等待成爲被動觸發的狀態
等事件觸發之後再進行, 本質是一個全局變量
運用了事件編程的思想

與線程鎖配合使用
一旦條件滿足就喚醒因等待滿足特定條件而睡眠的線程

優勢是 等條件的線程們全部在掛起等待 不會消耗內存

類似於線程池的信號系統

       pthread_cond_signal();      //喚醒一個線程
       pthread_cond_broadcast();   //喚醒所有線程 但是隻有一個人拿到鎖

       //使用流程:
           1.pthread_mutex_lock
           2.pthread_cond_wait //內部會先解鎖 然後等條件再加鎖
                               //保證每一個時間等待條件的人只有一個
                               //串行掛起 先解鎖後的所有人進入此行循環
           3.pthread_mutex_unlock

用戶校驗

1.setuid 設置用戶id 再之後的代碼以該id身份執行
2.getspnam 傳入用戶名 返回的是一個帶有用戶身份的指針(含有密文密碼)
getpwuid 得到uid (更好用)
3.crypt 對比明文與密文

1.模塊化 可以拆裝 宏內核
2.一個整體內核一塊崩潰全體崩潰 微內核 –linux
— 查看兩者區別

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章