天天看點

Linux-線程之間的同步與互斥

概述

由于線程共享程序的資源和位址空間,是以在對這些資源進行操作時,必須考慮到線程間資源通路的同步與互斥問題。這裡主要介紹Posix中兩種線程同步機制,分别為互斥鎖和信号量。這兩個同步機制可以通過互相調用對方來實作,但互斥鎖更适用于同時可用的資源是唯一的情況;信号量更适用于同時可用的資源為多個的情況。

互斥鎖

互斥鎖是用一種簡單的加鎖方法來控制對共享資源的原子操作。這個互斥鎖隻有兩種狀态,即上鎖和解鎖,可以把互斥鎖看做某種意義上的全局變量。在同一個時刻隻能有一個線程掌握某個互斥鎖,擁有上鎖狀态的線程能夠對共享資源進行操作。若其他線程希望上鎖一個已經被上鎖的互斥鎖,則該線程就會被挂起,直到上鎖的線程釋放掉互斥鎖為止。可以說,這把互斥鎖保證讓每個線程對共享資源按順序進行原子操作。

互斥鎖機制主要包括以下基本函數:

● 互斥鎖初始化:pthread_mutex_init()

● 互斥鎖上鎖:pthread_mutex_lock()

● 互斥鎖判斷上鎖:pthread_mutex_trylock()

● 互斥鎖解鎖:pthread_mutex_unlock()

● 消除互斥鎖:pthread_mutex_destroy()

其中,互斥鎖可以分為快速互斥鎖、遞歸互斥鎖和檢錯互斥鎖。這3種鎖的差別主要在于其它未占有互斥鎖的線程在希望得到互斥鎖時是否需要阻塞等待。快速互斥鎖是指調用線程會阻塞直至擁有互斥鎖的線程解鎖為止;遞歸互斥鎖能夠成功地傳回,并且增加調用線程在互斥上加鎖的次數而檢錯互斥鎖則為快速互斥鎖的非阻塞版本,它會立即傳回并傳回一個錯誤資訊。預設屬性為快速互斥鎖。

Linux-線程之間的同步與互斥
Linux-線程之間的同步與互斥

信号量

信号量就是作業系統中多用到的PV原子操作,它廣泛應用于程序或線程間的同步與互斥。信号量本質上是一個非負的整數計數器,它被用來控制對公共資源的通路。這裡先簡單複習一下PV原子操作的工作原理。詳細的請看部落格:http://blog.csdn.net/mybelief321/article/details/9086151

PV原子操作是對整數計數器信号量sem的操作。一次P操作使sem減1,而一次V操作使sem加1。程序(或線程)根據信号量的值來判斷是否對公共資源具有通路權限。當信号量sem的值≥0時,該程序(或線程)具有公共資源的通路權限;相反,當信号量sem的值<0時,該程序(或線程)就将阻塞直到信号量sem的值≥0為止。

PV原子操作主要用于程序或線程間的同步和互斥這兩種典型情況。若用于互斥,幾個程序(或線程)往往隻設定一個信号量sem,其操作流程如圖1所示。當信号量用于同步操作時,往往會設定多個信号量,并安排不同的初始值來實作它們之間的順序執行,其操作流程如圖2所示。

Linux-線程之間的同步與互斥

Linux實作了Posix的無名信号量,主要用于線程間的互斥與同步。這裡主要介紹幾個常見函數:

● sem_init()用于建立一個信号量,并初始化它的值。

● sem_wait()和sem_trywait()都相當于P操作,在信号量>0時,它們能将信号量的值減1。兩者的差別在于信号量<0時,sem_wait(0将會阻塞程序,而sem_trywait則會立即傳回。

● sem_post()相當于V操作,它将信号量的值加1,同時發出信号來喚醒等待的程序。

● sem_getvalue()用于得到信号量的值。

● sem_destroy()用于删除信号量。

Linux-線程之間的同步與互斥
Linux-線程之間的同步與互斥

繼續閱讀