1. 程式人生 > >Linux 線程編程2.0——線程同步-互斥鎖

Linux 線程編程2.0——線程同步-互斥鎖

oid 資源 不可 但是 ID 參數 sprintf ade 加鎖

當我們需要控制對共享資源的存取的時候,可以用一種簡單的加鎖的方法來控制。我們可以創建一個讀/寫程序,它們共用一個共享緩沖區,使用互斥鎖來控制對緩沖區的存取。 

  函數 pthread_mutex_init()用來生成一個互斥鎖。其函數原型如下:

#include<pthread.h>

int pthread_mutex_init(pthread_mutex_t *restrict mutexconst pthread_mutexattr_t *restrict attr)

第一個參數是互斥變量的地址,第二個參數設置互斥變量的屬性,大多數情況下.選擇默認屬性,則傳入空指針

NULL

  Pthread_mutex_lock()函數聲明開始用互斥鎖上鎖,此後的代碼直至調用 pthread_mutex_ unlock()為止,均被上鎖,即同一時間只能被一個線程調用執行。當一個線程執行 pthread_mutex_lock()處時,如果該鎖此時被另一個線程使用,那麽此線程被阻塞,線程一直阻塞知道另一個線程釋放此互斥鎖。這兩個函數原型是:

 int pthread_mutex_lock(pthread_mutex_t *mutex)

 int pthread_mutex_unlock(pthread_mutex_t *mutex)

  兩個函數的參數都是互斥變量的地址。函數執行成功返回

0,否則返回錯誤號。

  互斥鎖使用很方便,但是有一個缺點是使用互斥鎖的過程中很有可能會出現死鎖:兩個線程試圖同時占有兩個資源,並按不同的次序鎖定相應的互斥鎖,例如兩個線程都需要鎖定互斥鎖 l 和互斥鎖 2A 線程鎖定了互斥鎖 lB 線程了鎖定互斥鎖 2,此時如果 A 線程在解除互斥鎖 l 之前又去鎖定互斥鎖 2,而 B 恰好又需要去鎖定互斥鎖 l,這時就出現了死鎖。看起來像是繞口令,通俗一點的來解釋:線程 A 和線程 B 都需要獨占使用 2 個資源,但是他們都分別先占據了一個資源,然後有相互等待另外一個資源的釋放,這樣的形成了一個死鎖。此時我們可以使用函數 pthread_mutex_trylock(),它是函數

pthread_mutex_lock()的非阻塞函數,當它發現死鎖不可避免時,它會通過 errno 返回 EBUSY,我們可以針對死鎖做出相應的處理。Pthread_mutex_try_lock()的函數原型是:

int pthread_mutex _trylock( pthread_mutex_t*mutex)

  當互斥鎖不再使用的時候,應當釋放互斥變量,函數 pthread _mutex.destory()用來釋放一個互斥變量。

代碼:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

char buffer[128];
int buffer_has_data=0;
pthread_mutex_t mutex;

void write_buffer (char *data)
{
    /* 鎖定互斥鎖*/
    pthread_mutex_lock (&mutex);
    if (buffer_has_data == 0)
    {
        sprintf( buffer, "%s", data);
        buffer_has_data=1;
    }
    /* 打開互斥鎖*/
    pthread_mutex_unlock(&mutex);
}

void  read_buffer(void)
{
    while(1){
        /* 鎖定互斥鎖*/
        pthread_mutex_lock(&mutex);
        if(buffer_has_data == 1)
        {
            printf("Read buffer, data = [%s]\n", buffer);
            buffer_has_data=0;
        }
        /* 打開互斥鎖*/
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
}

int main ( int argc, char **argv )
{
    char input[128];
    pthread_t reader;
    /* 用默認屬性初始化一個互斥鎖對象*/
    pthread_mutex_init( &mutex, NULL );
    pthread_create(&reader, NULL, (void *)(read_buffer), NULL);
    while( 1 )
    {
        scanf( "%s", input );
        write_buffer( input );
    }
    return 0;
}

Linux 線程編程2.0——線程同步-互斥鎖