linux多线程之互斥锁


基本概念:

互斥变量是用pthread_mutex_t数据类型表示的。在使用互斥变量以前,必须首先对它进行初始化,可以把它设置为常量PTHREAD_MUTEX_INITIALIZER(只适用于静态分配的互斥量),也可以通过调用pthread_mutex_init函数进行初始化。如果动态分配互斥量(例如,通过调用malloc函数),在释放内存前需要调用pthread_mutex_destroy。


一、锁的初始化与销毁

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

NAME
       pthread_mutex_destroy,  pthread_mutex_init  -  destroy and initialize a
       mutex

SYNOPSIS
       #include <pthread.h>

       int pthread_mutex_destroy(pthread_mutex_t *mutex);
       int pthread_mutex_init(pthread_mutex_t *restrict mutex,
              const pthread_mutexattr_t *restrict attr);
       pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

两个函数的返回值:若成功,返回0;否则,返回错误码


二、加锁解锁

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

NAME
       pthread_mutex_lock, pthread_mutex_trylock, pthread_mutex_unlock - lock and unlock a mutex

SYNOPSIS
       #include <pthread.h>

       int pthread_mutex_lock(pthread_mutex_t *mutex);
       int pthread_mutex_trylock(pthread_mutex_t *mutex);
       int pthread_mutex_unlock(pthread_mutex_t *mutex);
所有函数的返回值:若成功,返回0;否则返回错误码


如果线程不希望被阻塞,它可以使用pthread_mutex_trylock尝试对互斥量进行加锁。如果调用pthread_mutex_trylock时互斥量处于未锁住状态,那么pthread_mutex_trylock将锁住互斥量,不会出现阻塞直接返回0,否则pthread_mutex_trylock就会失败,不能锁住互斥量,返回EBUSY.


三、支持超时的阻塞lock

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

NAME
       pthread_mutex_timedlock - lock a mutex (ADVANCED REALTIME)

SYNOPSIS
       #include <pthread.h>
       #include <time.h>

       int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,
              const struct timespec *restrict abs_timeout);
返回值:若成功,返回0;否则,返回错误码编号


当线程试图获取一个已加锁的互斥量时,pthread_mutex_timedlock函数在达到超时时间值时,不会对互斥量进行加锁,而是返回错误码ETIMEDOUT


四、互斥量属性

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

NAME
       pthread_mutexattr_destroy, pthread_mutexattr_init - destroy and initialize the mutex attributes object

SYNOPSIS
       #include <pthread.h>

       int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
       int pthread_mutexattr_init(pthread_mutexattr_t *attr);
两个函数的返回值:若成功,返回0;否则,返回错误码编号


互斥量属性是用pthread_mutexattr_t结构表示的。对于非默认属性,可以用pthread_mutexattr_init初始化pthread_mutexattr_t结构,用pthread_mutexattr_destroy来反初始化。pthread_mutexattr_init函数将用默认的互斥量属性初始化pthread_mutexattr_t结构。

值得注意的3个属性是:

1.进程共享属性:如果进程共享互斥量属性设置为PTHREAD_PROCESS_SHARED,从多个进程彼此之间共享的内存数据块中分配的互斥量就可以用于这些进程的同步。

2.健壮属性:互斥量健壮属性与在多个进程共享的互斥量有关

3.类型属性:类型互斥量属性控制着互斥量的锁定特性,可以用pthread_mutexattr_gettype函数得到互斥量类型属性,用pthread_mutexattr_settype函数修改互斥量类型属性。


例子1,静态分配互斥量:gcc pthread_mutex.c -pthread

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

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

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

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);

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

    // detach thread3
    err = pthread_detach(thread2);
    if (err != 0) {
        Perror("can't detach thread2\n");
    }

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

    sleep(10);
    printf("The num is %d\n", num);

    return 0;
}


例子2,动态分配互斥量:gcc pthread_mutex.c -pthread

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

static int num = 0;
static int count = 100000;
static pthread_mutex_t* pmutex;


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

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(pmutex);
        num += 1;
        pthread_mutex_unlock(pmutex);
    }
}

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

    // init mutex
    pmutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
    if (pthread_mutex_init(pmutex, NULL) != 0)
        Perror("pthread_mutex_init failed");

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

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

    // detach thread3
    err = pthread_detach(thread2);
    if (err != 0) {
        Perror("can't detach thread2\n");
    }

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

    sleep(10);
    printf("The num is %d\n", num);

    // destroy
    pthread_mutex_destroy(pmutex);
    free(pmutex);

    return 0;
}


ps:多进程间的互斥锁不在本文讨论范围,避免死锁可参考文章:互斥量避免死锁


参考:《unix环境高级编程》·第三版

End;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值