在多線程編程中,出於各種原因我們會用到鎖或者信號量等各種機制對一些操作進行控制,這里面就講述linux C編程時,常用的兩種方式:信號量方式 和 鎖方式
鎖:用來做互斥,用於保護某個資源在當下只能被多個線程中的一個訪問,用於一個進程的多線程之間
信號量:用來做同步,用於保證多個線程之間按照既定順序執行步驟,可以用於一個進程的多線程,據說也可以用於多個進程
wxy:鎖是為了保護某個資源,從上鎖的那一刻,如果不涉及資源(多線程可訪問的那些變量?或者叫全局變量,或者類中的成員變量等等...),照樣可以走下去
信號量是為了同步的,從上信號量那一刻,就不能動了,除非另一個想成給我發信號(post),說你可以繼續了,與是我才繼續走下去
一:Mutex(鎖)
1,用法舉例(經試驗)
//0.頭文件引入 #include <mutex> //1.定義鎖 mutex mutex_me;
++++++線程1+++++++++ +++++++++線程2+++++++++
//2.上鎖 //2.上鎖 mutex_me.lock() mutex_me.lock() /*資源*/ //3.解鎖 mutex_me.unlock() /*資源*/ //3.解鎖
mutex_me.unlock()
2,函數解析
void lock() { int __e = __gthread_mutex_lock(&_M_mutex); } static inline int __gthread_mutex_lock (__gthread_mutex_t *__mutex){ if (__gthread_active_p ()) //如果當前線程是活躍的 return __gthrw_(pthread_mutex_lock) (__mutex); else return 0; }
二,信號量
1,用法舉例(未經試驗)
//0.頭文件引入
#include <semaphore.h>
//1.定義/創建信號量
sem_t semaphoretcpItem;
sem_init(&semaphoretcpItem, 0, 1);
++++++線程1+++++++++ +++++++++線程2+++++++++ +++++++線程3++++++
//step1:等待信號量 //step2.第一次釋放信號量
while(true){ sem_post(&semaphoretcpItem);
sem_wait(&semaphoretcpItem);
//step3.第二次釋放信號量
sem_post(&semaphoretcpItem);
step4 * 3次
}
解析:
1.wait的時候要求信號量>0,而初始信號量時1,因此wait語句順利通過,通過的同時信號量-1,此時線程1中的while第一輪循環是可以執行的;
2.如果線程2和3都沒有什么動作,則線程1在進入第二輪循環的時候阻塞在那里,直到線程2或3有post,於是信號量+1;
3,整體總結起來就是:線程1是否往下執行就看其他線程是否有動作,這樣的邏輯就好比生產者消費者
我(線程1)不瞎執行,累夠嗆,只有需要我干活的時候(其他線程)我再執行....
2,相關函數解析
sem_init():用來初始化一個信號量。
它的原型為:extern int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));
sem為指向信號量結構的一個指針;
pshared不為0時此信號量在進程間共享,否則只能為當前進程的所有線程共享;
value給出了信號量的初始值。
sem_post( sem_t *sem ):用來增加信號量的值。
當有線程阻塞在這個信號量上時,調用這個函數會使其中的一個線程不在阻塞,選擇機制同樣是由線程的調度策略決定的。
sem_wait( sem_t *sem ):被用來阻塞當前線程直到信號量sem的值大於0,解除阻塞后將sem的值減一,表明公共資源經使用后減少。
sem_trywait ( sem_t *sem ):是函數sem_wait()的非阻塞版本,它直接將信號量sem的值減一。
sem_destroy(sem_t *sem):用來釋放信號量sem。