前面我们讲了chromium 的线程模型是尽可能不用锁,方法主要是尽量避免访问并发资源以及减小锁的控制范围来实现。
所以当我们进行多线程编程时,首先要问一下自己:我们真的需要锁或者条件变量吗?在chrome代码中,消息传递是非常普遍的(通过TaskRunner 和 PostTask),底层在非常必要的时候才会用到锁和条件变量。
另外要说明的是:
1. 条件变量在windows平台基本上不可能实现。
2. 很多时候用户只是想获得一个布尔值。如果消息传递不可用,请使用WaitableEvent
当我们不得不使用锁或者条件变量的时候,请按照下面的实践实现。
1. 在一个方法里面申请了锁,在这个方法退出前释放锁
2. 共享变量需要说明哪个互斥锁在保护他,或者说明为什么不需要保护
int accesses_; // count of accesses (guarded by mu_)
int table_size_; // no. of elements in table (readonly after init)
3. 互斥锁需要说明他所保护的对象
Lock mu_; // protects accesses_, list_, count_
// invariant: count_ == number of elements in linked-list list_
4. 有多个锁的时候,说明锁的前后顺序
Lock mu0_; // protects foo_ (acquired before mu1_)
5. 不要在回调函数里面用锁
6. 使用锁的函数说明清楚,比如在进入之前不能拥有某个锁
是不是很复杂?即使这样,使用锁还是会有问题,引起死锁或者资源竞争。
所以,我们还是能不用锁就不用锁吧。chrome的多线程共享资源就是通过消息传递来实现的。关于这个话题,我们还需要继续深入。