線程是CPU的最小調度單元,每個核上都可以運行一個線程。
多進程
缺點:
進程是互相隔離的,多進程之間的通信和同步是效率低。
CPU進行進程切換效率低
創建一個進程比創建線程耗費的內存多
優點:
單核CPU可以完成多任務,在宏觀上並行。
線程:
優點:
線程保留了多進程的多任務特性,但是線程之間的通信效率更高,切換線程的效率也更高。
多核的CPU可以保證多線程可以同時運行在多個核上(CPU不能保證多個進程可以同時運行在多核上)
使CPU利用率更高
線程就是在保留了進程的多任務特性的基礎上,優化了進程的通信和進程切換的效率。
線程創建與回收
(1)pthread_create 用來創造子線程的 創建成功立刻調用一次
(2)pthread_join 用來等待(阻塞)回收子線程
(3)pthread_detach 用來分離子線程,分離後主線程不必再去回收子線程
(4)pthread_attr_init 屬性初始化的函數
線程取消
(1)pthread_cancel 一般都是主線程調用該函數去取消(讓它趕緊死)子線程
(2)pthread_setcancelstate 子線程設置自己是否允處理cancel信號
(3)pthread_setcanceltype 取消模式(異步取消<立刻死> or 同步取消<等待適當時機死>)
線程函數退出相關
(1)pthread_exit與return退出
(2)pthread_cleanup_push 註冊一個清理函數 清理鎖
(3)pthread_cleanup_pop 註銷清理函數
線程私有數據
int pthread_key_creadte(pthread_key_t *key,void (*destr_fuction) (void *)); 創建鍵值
int pthread_setspecific(pthread_key_t key,const void * pointer)); 設置
void * pthread_getspecific(pthread_key_t key); 獲取
int pthread_key_delete(ptherad_key_t key); 刪除
主線程退出:
主線程中如果從main函數返回或是調用了exit函數退出主線程,則整個進程終止,此時所有的其他線程也將終
主線程調用pthread_exit函數,則僅僅是主線程消亡,進程不會結束
線程取消:
線程取消就是向目標線程發送Cancel信號,但對這個信號的處理方式由線程自身決定(取消)。
if 是否接受取消信號 then
if 異步取消 then
立刻結束
else
運行到下個取消點結束(多數阻塞函數的調用位置都是取消點 pthread_join()、pthread_testcancel()、pthread_cond_wait()、pthread_cond_timedwait()、sem_wait()、sigwait())
end
end
觸發終止線程的兩種方式:
正常終止 :return 和主動pthread_exit(),
非正常終止:外部干擾導致退出
無論是那種方式退出 線程的資源都會被釋放
對於非正常終止 要保證退出前資源可以正確清理 使用 pthread_cleanup_push/pthread_cleanup_pop。在兩個函數中間的終止操作會調用清理函數,清理資源(如釋放鎖)
終止後清理資源方式:
線程爲分離狀態:操作系統自動回收資源。
pthread_join() :其他進程阻塞等待線程結束 並釋放資源
其他:當線程退出時,線程佔用的資源並不會釋放。
什麼是線程同步???
線程同步就是控制線程的執行順序,保證線程安全(多個線程訪問同時訪問同一個數據)
同步方式:
互斥鎖:
pthread_mutex_init pthread_mutex_destroy
pthread_mutex_lock pthread_mutex_unlock
信號量:
int sem_init
int sem_wait(sem_t *sem); 給信號量減1;對一個值爲0的信號量調用sem_wait,這個函數將會等待直到有其它線程使它不再是0爲止。
int sem_post(sem_t *sem); 給信號量的值加1;
int sem_destroy
條件變量
pthread_cond_init pthread_cond_destroy
pthread_cond_wait pthread_cond_signal/pthread_cond_broadcast
互斥鎖不同,條件變量是用來等待而不是用來上鎖的。條件變量用來自動阻塞一個線程,直到某特殊情況發生爲止。一個線程等待"條件變量的條件成立"而掛起;另一個線程使"條件成立"(給出條件成立信號)。
多線程爲什麼需要同步??
爲了解決多線程間共享數據問題,如果數據只是讀那麼沒有影響。
爲什麼共享數據會發生問題???
對共享數據的操作如果不是原子不可打斷的(單個彙編指令完成的操作爲原子 或 加鎖),那麼在執行過程中線程可能會被掛起,其他線程也可以運行操作這個數據,就會導致線程見數據不安全。
例子:
x++和++x。
其實類似x++, x+=2, ++x這樣的操作在多線程環境下是需要同步的。因爲X86會按三條指令的形式來處理這種語句:從內存中讀x的值到寄存器中,對寄存器加1,再把新值寫回x 所處的內存地址。
例如有兩個線程,它們按照如下順序執行(注意讀x和寫回x是原子操作,兩個線程不能同時執行):
time Thread 1 Thread 2
0 load eax, x
1 load eax x
2 add eax, 1 add eax, 1
3 store x, eax
4 store x, eax
中斷的位置對程序的輸出結果是有影響的,這就是導致多線程問題的根本原因。所以引入線程同步解決,保證某部分數據或代碼的操作是原子的。
同步、互斥區別??
互斥不要求線程按一定順序執行,同步是爲了讓線程按一定順序執行。
同步是指在互斥的基礎上(大多數情況),通過其它機制實現訪問者對資源的有序訪問。可以說同步是特殊的互斥。
互斥鎖與信號量:
互斥鎖是一種特殊的信號量,值只能是0 1 ,信號量值 可以是任意非0整數。互斥鎖的加鎖和解鎖操作必須在同一線程中,信號量可以一個線程釋放,另一個線程得到。
條件變量:條件變量用於同步 阻塞的等待某一條件滿足 互斥鎖是爭奪資源 用於互斥
爲什麼要和互斥鎖一起使用???
https://www.jb51.net/article/102764.htm