互斥锁

锁标志位:
文件: switch_apr.h

  1. /** Lock Flags */
  2. #define SWITCH_MUTEX_DEFAULT 0x0 /**< platform-optimal lock behavior */
  3. #define SWITCH_MUTEX_NESTED 0x1 /**< enable nested (recursive) locks */
  4. #define SWITCH_MUTEX_UNNESTED 0x2 /**< disable nested locks */

初始化锁(递归锁)

  1. static struct {
  2. switch_hash_t *files;
  3. switch_hash_t *lists;
  4. switch_mutex_t *files_mutex;
  5. switch_mutex_t *lists_mutex;
  6. switch_memory_pool_t *pool;
  7. } globals;
  8. switch_mutex_init(&globals.lists_mutex, SWITCH_MUTEX_NESTED, globals.pool);

使用锁

  1. switch_mutex_lock(globals.lists_mutex);
  2. bl = switch_core_hash_find(globals.lists, argv[1]);
  3. switch_mutex_unlock(globals.lists_mutex);

释放锁

  1. switch_mutex_destroy(globals.mutex);

递归锁和非递归锁区别

Mutex可以分为递归锁(recursive mutex)非递归锁(non-recursive mutex)。可递归锁也可称为可重入锁(reentrant mutex),非递归锁又叫不可重入锁__(non-reentrant mutex)。 二者唯一的区别是,同一个线程可以多次获取同一个递归锁,不会产生死锁。而如果一个线程多次获取同一个非递归锁,则会产生死锁。 引用自: https://blog.csdn.net/zouxinfox/article/details/5838861


读写锁

此处有一个实际的使用场景:

  1. mod_commands.c里面的bgapi会启动线程执行任务
  2. 在模块shutdown的时候, 需要判断是否有线程还在运行, 有的话就等待
  3. bgapi启动的各个线程需要能并发运行

创建读写锁

  1. //静态变量, 只在本文件内有效
  2. static switch_thread_rwlock_t *bgapi_rwlock = NULL;
  3. //初始化时, 创建读写锁
  4. switch_thread_rwlock_create(&bgapi_rwlock, pool);

异步线程读取锁

rdlock为读锁, 所以多个线程并发访问的时候, 不会 因为锁而等待.

  1. static void *SWITCH_THREAD_FUNC bgapi_exec(switch_thread_t *thread, void *obj)
  2. {
  3. ...
  4. switch_thread_rwlock_rdlock(bgapi_rwlock);
  5. ...
  6. //执行api命令, 以事件返回命令执行结果
  7. ...
  8. switch_thread_rwlock_unlock(bgapi_rwlock);
  9. return NULL;
  10. }

关闭时释放锁

switch_thread_rwlock_trywrlock尝试写锁, 如果上面的线程还在读锁里面, 则获取写锁失败, 会继续等待.
直到所有的读锁执行完毕退出, 此处才能获取写锁成功.
也就达到等待所有线程执行完毕的目的了.

  1. SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_commands_shutdown)
  2. {
  3. int x;
  4. for (x = 30; x > 0; x--) {
  5. if (switch_thread_rwlock_trywrlock(bgapi_rwlock) == SWITCH_STATUS_SUCCESS) {
  6. switch_thread_rwlock_unlock(bgapi_rwlock);
  7. break;
  8. }
  9. if (x == 30) {
  10. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for bgapi threads.\n");
  11. }
  12. switch_yield(1000000);
  13. }
  14. if (!x) {
  15. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Giving up waiting for bgapi threads.\n");
  16. }
  17. return SWITCH_STATUS_SUCCESS;
  18. }

wrlock和trywrlock区别?

trywrlock和wrlock功能基本一致, 唯一的区别是如果获取不到锁, 则trywrlock直接返回失败, 而不是像wrlock进入等待状态.
trywrlock返回失败条件: 另一个线程正在read或者write.