关于pthread_mutex_lock使用

本文详细介绍了pthread互斥锁的创建、初始化、获取、释放及销毁等操作,涵盖了阻塞调用、非阻塞调用及超时调用等多种场景,并解析了相关函数的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于pthread_mutex_lock使用

关于pthread_mutex_lock常用函数如下:

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

int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex, const struct timespec *restrict abs_timeout);

a、创建互斥锁

互斥锁的类型是 pthread_mutex_t ,所以定义一个变量就是创建了一个互斥锁:

pthread_mutex_t mtx;

b、初始化互斥锁

使用这个互斥锁,需要对互斥锁进行初始化, 使用函数 pthread_mutex_init() 对互斥锁进行初始化操作,未进行初始化,则创建的互斥锁不会生效:

//第二个参数为 NULL,互斥锁的属性会设置为默认属性
pthread_mutex_init(&mtx, NULL);

c、获取互斥锁

在进行互斥操作的时候, 应该先"拿到锁"再执行需要互斥的操作,否则可能会导致多个线程都需要访问的数据结果不一致。

下面是获取锁的操作:

d、阻塞调用

pthread_mutex_lock(&mtx);

这个操作是阻塞调用的,也就是说,如果这个锁此时正在被其它线程占用, 那么 pthread_mutex_lock() 调用会进入到这个锁的排队队列中,并会进入阻塞状态, 直到拿到锁之后才会返回。

e、非阻塞调用

如果不想阻塞,而是想尝试获取一下,如果锁被占用就不用,如果没被占用那就用, 可以使用 pthread_mutex_trylock() 函数。 这个函数和 pthread_mutex_lock() 用法一样,只不过当请求的锁正在被占用的时候, 不会进入阻塞状态,而是立刻返回,并返回一个错误代码 EBUSY,意思是说, 有其它线程正在使用这个锁。

int err = pthread_mutex_trylock(&mtx);
if(0 != err) {
    if(EBUSY == err) {
        //The mutex could not be acquired because it was already locked.
    }
}

f、超时调用

如果不想不断的调用 pthread_mutex_trylock() 来测试互斥锁是否可用, 而是想阻塞调用,但是增加一个超时时间,那么可以使用 pthread_mutex_timedlock() 来解决, 其调用方式如下:

struct timespec abs_timeout;
abs_timeout.tv_sec = time(NULL) + 1;
abs_timeout.tv_nsec = 0;

int err = pthread_mutex_timedlock(&mtx, &abs_timeout);
if(0 != err) {
    if(ETIMEDOUT == err) {
        //The mutex could not be locked before the specified timeout expired.
    }
}

上面代码的意思是,阻塞等待线程锁,但是只等1秒钟,一秒钟后如果还没拿到锁的话, 那就返回,并返回一个错误代码 ETIMEDOUT,意思是超时了。

其中 timespec 定义在头文件 time.h 中,其定义如下

struct timespec
{
    __time_t tv_sec;        /* Seconds.  */
    long int tv_nsec;       /* Nanoseconds.  */
};

还需要注意的是,这个函数里面的时间,是绝对时间,所以这里用 time() 函数返回的时间增加了 1 秒。

g、释放互斥锁

用完互斥锁,一定要记得释放,不然下一个想要获得这个锁的线程, 就只能去等着了,如果那个线程很不幸的使用了阻塞等待…。

释放互斥锁比较简单,使用 pthread_mutex_unlock() 即可:

pthread_mutex_unlock(&mtx);

h、销毁线程锁

通过 man pthread_mutex_destroy 命令可以看到 pthread_mutex_destroy() 函数的说明, 在使用此函数销毁一个线程锁后,线程锁的状态变为"未定义"。有的 pthread_mutex_destroy 实现方式,会使线程锁变为一个不可用的值。一个被销毁的线程锁可以被 pthread_mutex_init() 再次初始化。对被销毁的线程锁进行其它操作,其结果是未定义的。

对一个处于已初始化但未锁定状态的线程锁进行销毁是安全的。尽量避免对一个处于锁定状态的线程锁进行销毁操作。

销毁线程锁的操作如下:

pthread_mutex_destroy(&mtx)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值