CritCal临界锁的实现
Linux下临界锁的实现
使用posix线程接口实现
实现文件: webRTC/base/critcalsection.h
暴露给外部使用的类CritScope
class SCOPED_LOCKABLE CritScope {
public:
explicit CritScope(const CriticalSection* cs) EXCLUSIVE_LOCK_FUNCTION(cs);
~CritScope() UNLOCK_FUNCTION();
private:
const CriticalSection* const cs_;
RTC_DISALLOW_COPY_AND_ASSIGN(CritScope);
};
CritScope::CritScope(const CriticalSection* cs) : cs_(cs) { cs_->Enter(); }
CritScope::~CritScope() { cs_->Leave(); }
CritScope很明显是封装了CritcalSection类
从实现细节上可以推断出调用方法应该是这样的
crit是调用类的private私有变量
调用类的某个方法内
xx_class::xx_method {
{
CritScope crit(&crit_);
....
}
....
}
构造时初始化和进入临界区 析构时退出临界区 典型的C++写法
CriticalSection的实现
Linux下采用pthread_mutex实现
mutex属性设置
CriticalSection::CriticalSection() {
#if defined(WEBRTC_WIN)
InitializeCriticalSection(&crit_);
#else
#if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
lock_queue_ = 0;
owning_thread_ = 0;
recursion_ = 0;
semaphore_ = dispatch_semaphore_create(0);
#else
pthread_mutexattr_t mutex_attribute;
pthread_mutexattr_init(&mutex_attribute);
pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex_, &mutex_attribute);
pthread_mutexattr_destroy(&mutex_attribute);
#endif
CS_DEBUG_CODE(thread_ = 0);
CS_DEBUG_CODE(recursion_count_ = 0);
#endif
}
构造方法中,将锁的属性设置为了PTHREAD_MUTEX_RECURSIVE
设置RECURSIVE后,线程锁将可以重复的获得而不会阻塞
通俗的说就是
默认的设置下 锁lock后必须unlock 才能再次lock
设置RECURSIVE后 锁lock后即使没有unlock 也可以成功再次lock
原理就是设置RECURSIVE后 锁会进行lock的计数 lock和unlock的数目对应后 其他线程才能获得锁
举个例子 如果用有一个socket链表需要维护
链表类有两个操作 add和delect
socket链表表示是一个缓冲区buffer 那么udp接收线程可以访问它 tcp接收线程也可以(也可以是有多个udp接收线程) 此时必须等待所有add操作都结束了才能进行delete
这就是互斥锁的属性设置为RECURSIVE的意义
CritScope和TryCritScope的意义就在于做共享资源的临界保护 防止同时操作引起错误
也就分别对于posix接口的pthread_mutex_lock和pthread_mutex_trylock
测试代码git地址
https://github.com/sliver-chen/webRTCTutorial/blob/master/CritScope/CritTest.cpp