1. 程式人生 > >linux多執行緒之自旋鎖

linux多執行緒之自旋鎖

基本概念:

何謂自旋鎖?它是為實現保護共享資源而提出一種鎖機制。其實,自旋鎖與互斥鎖比較類似,它們都是為了解決對某項資源的互斥使用。無論是互斥鎖,還是自旋鎖,在任何時刻,最多隻能有一個保持者,也就說,在任何時刻最多隻能有一個執行單元獲得鎖。但是兩者在排程機制上略有不同。對於互斥鎖,如果資源已經被佔用,資源申請者只能進入睡眠狀態。但是自旋鎖不會引起呼叫者睡眠,如果自旋鎖已經被別的執行單元保持,呼叫者就一直迴圈在那裡看是否該自旋鎖的保持者已經釋放了鎖,"自旋"一詞就是因此而得名。


一、初始化和銷燬鎖

PTHREAD_SPIN_DESTROY(P)    POSIX Programmer's Manual   PTHREAD_SPIN_DESTROY(P)

NAME
       pthread_spin_destroy,  pthread_spin_init - destroy or initialize a spin
       lock object (ADVANCED REALTIME THREADS)

SYNOPSIS
       #include <pthread.h>

       int pthread_spin_destroy(pthread_spinlock_t *lock);
       int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
兩個函式的返回值:若成功,返回0;否則,返回錯誤編號
關於pthread_spin_init函式的引數pshard,單程序可以設定成PTHREAD_PROCESS_SHARED

二、加鎖與解鎖

PTHREAD_SPIN_LOCK(P)       POSIX Programmer's Manual      PTHREAD_SPIN_LOCK(P)

NAME
       pthread_spin_lock,  pthread_spin_trylock  -  lock  a  spin  lock object
       (ADVANCED REALTIME THREADS)

SYNOPSIS
       #include <pthread.h>

       int pthread_spin_lock(pthread_spinlock_t *lock);
       int pthread_spin_trylock(pthread_spinlock_t *lock);
       int pthread_spin_unlock(pthread_spinlock_t *lock);
兩個函式的返回值:若成功,返回0;否則,返回錯誤編號

例子1,互斥鎖的耗時, gcc pthread_mutex.c -pthread -o mutex:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/timeb.h>

static int num = 0;
static int count = 10000000;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void Perror(const char *s)
{
    perror(s);
    exit(EXIT_FAILURE);
}

long long getSystemTime() {
    struct timeb t;
    ftime(&t);
    return 1000 * t.time + t.millitm;
}

void* fun2(void *arg)
{
    pthread_t thread_id = pthread_self();
    printf("the thread2 id is %ld\n", (long)thread_id);
    int i = 1;
    for (; i<=count; ++i) {
        pthread_mutex_lock(&mutex);
        num += 1;
        pthread_mutex_unlock(&mutex);
    }
}

int main()
{
    int err;
    pthread_t thread1;
    pthread_t thread2;

    thread1 = pthread_self();
    printf("the thread1 id is %ld\n", (long)thread1);

    long long start = getSystemTime();

    // Create thread
    err = pthread_create(&thread2, NULL, fun2, NULL);
    if (err != 0) {
        Perror("can't create thread2\n");
    }

    int i = 1;
    for (; i<=count; ++i) {
        pthread_mutex_lock(&mutex);
        num += 1;
        pthread_mutex_unlock(&mutex);
    }

    pthread_join(thread2, NULL);
    long long end = getSystemTime();

    printf("The num is %d, pay %lld ms\n", num, (end-start));

    return 0;
}

例子2,自旋鎖的耗時,gcc pthread_spin.c -pthread -o spin:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/timeb.h>

static int num = 0;
static int count = 10000000;
static pthread_spinlock_t spin;

void Perror(const char *s)
{
    perror(s);
    exit(EXIT_FAILURE);
}

long long getSystemTime() {
    struct timeb t;
    ftime(&t);
    return 1000 * t.time + t.millitm;
}

void* fun2(void *arg)
{
    pthread_t thread_id = pthread_self();
    printf("the thread2 id is %ld\n", (long)thread_id);
    int i = 1;
    for (; i<=count; ++i) {
        pthread_spin_lock(&spin);
        num += 1;
        pthread_spin_unlock(&spin);
    }
}

int main()
{
    int err;
    pthread_t thread1;
    pthread_t thread2;

    pthread_spin_init(&spin, PTHREAD_PROCESS_PRIVATE);

    thread1 = pthread_self();
    printf("the thread1 id is %ld\n", (long)thread1);

    long long start = getSystemTime();

    // Create thread
    err = pthread_create(&thread2, NULL, fun2, NULL);
    if (err != 0) {
        Perror("can't create thread2\n");
    }

    int i = 1;
    for (; i<=count; ++i) {
        pthread_spin_lock(&spin);
        num += 1;
        pthread_spin_unlock(&spin);
    }

    pthread_join(thread2, NULL);
    long long end = getSystemTime();

    printf("The num is %d, pay %lld ms\n", num, (end-start));
    pthread_spin_destroy(&spin);
    return 0;
}

執行結果,可以看到某些條件下,自旋鎖是比較快的:


參考:《unix環境高階程式設計》·第三版

End;