互斥锁
锁标志位:
文件: switch_apr.h
/** Lock Flags */
#define SWITCH_MUTEX_DEFAULT 0x0 /**< platform-optimal lock behavior */
#define SWITCH_MUTEX_NESTED 0x1 /**< enable nested (recursive) locks */
#define SWITCH_MUTEX_UNNESTED 0x2 /**< disable nested locks */
初始化锁(递归锁)
static struct {
switch_hash_t *files;
switch_hash_t *lists;
switch_mutex_t *files_mutex;
switch_mutex_t *lists_mutex;
switch_memory_pool_t *pool;
} globals;
switch_mutex_init(&globals.lists_mutex, SWITCH_MUTEX_NESTED, globals.pool);
使用锁
switch_mutex_lock(globals.lists_mutex);
bl = switch_core_hash_find(globals.lists, argv[1]);
switch_mutex_unlock(globals.lists_mutex);
释放锁
switch_mutex_destroy(globals.mutex);
递归锁和非递归锁区别
Mutex可以分为递归锁(recursive mutex)和非递归锁(non-recursive mutex)。可递归锁也可称为可重入锁(reentrant mutex),非递归锁又叫不可重入锁__(non-reentrant mutex)。 二者唯一的区别是,同一个线程可以多次获取同一个递归锁,不会产生死锁。而如果一个线程多次获取同一个非递归锁,则会产生死锁。 引用自: https://blog.csdn.net/zouxinfox/article/details/5838861
读写锁
此处有一个实际的使用场景:
- mod_commands.c里面的bgapi会启动线程执行任务
- 在模块shutdown的时候, 需要判断是否有线程还在运行, 有的话就等待
- bgapi启动的各个线程需要能并发运行
创建读写锁
//静态变量, 只在本文件内有效
static switch_thread_rwlock_t *bgapi_rwlock = NULL;
//初始化时, 创建读写锁
switch_thread_rwlock_create(&bgapi_rwlock, pool);
异步线程读取锁
rdlock为读锁, 所以多个线程并发访问的时候, 不会 因为锁而等待.
static void *SWITCH_THREAD_FUNC bgapi_exec(switch_thread_t *thread, void *obj)
{
...
switch_thread_rwlock_rdlock(bgapi_rwlock);
...
//执行api命令, 以事件返回命令执行结果
...
switch_thread_rwlock_unlock(bgapi_rwlock);
return NULL;
}
关闭时释放锁
switch_thread_rwlock_trywrlock尝试写锁, 如果上面的线程还在读锁里面, 则获取写锁失败, 会继续等待.
直到所有的读锁执行完毕退出, 此处才能获取写锁成功.
也就达到等待所有线程执行完毕的目的了.
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_commands_shutdown)
{
int x;
for (x = 30; x > 0; x--) {
if (switch_thread_rwlock_trywrlock(bgapi_rwlock) == SWITCH_STATUS_SUCCESS) {
switch_thread_rwlock_unlock(bgapi_rwlock);
break;
}
if (x == 30) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for bgapi threads.\n");
}
switch_yield(1000000);
}
if (!x) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Giving up waiting for bgapi threads.\n");
}
return SWITCH_STATUS_SUCCESS;
}
wrlock和trywrlock区别?
trywrlock和wrlock功能基本一致, 唯一的区别是如果获取不到锁, 则trywrlock直接返回失败, 而不是像wrlock进入等待状态.
trywrlock返回失败条件: 另一个线程正在read或者write.