void Close ()
{
Enter A ; // 完整代码为 EnterCriticalSection (&b); 以下都按此简写。
Enter B;
Leave B;
Leave A;
}
?
void Read ()
{
Enter A;
Enter B;
Leave A;
Leave B;
}
【0】上述的代码会遇到死锁吗?
我的理解是,
【1】Enter顺序一致
【2】每个Enter都正常配对Leave了,但leave顺序可能不一致
【3】其它非互斥代码均正确 ,不捣乱。
多个锁在上述前提下,肯定不会死锁。 这对吗?
------解决思路----------------------
应该不会死锁,无论A或B被占用,企图线程都耐心等待,直到退出
------解决思路----------------------
应该要做逻辑分析,具体问题具体分析吧
------解决思路----------------------
最好的做法还是进入,退出都是一样的,这样才能保证。
------解决思路----------------------
原则时 : 使用时 进入,用完马上 退出,占用时间 越短越好
------解决思路----------------------
A 这个总锁有什么用呢?
如果访问子对象都需要先获得总锁,并发性已经受限,有没有子锁都不能扩大了。
如果访问子对象不需要总锁,总锁只用在 Open/Close 就没有什么作用了
我觉得应该是这样,每一个子对象都有一个锁 obj.sub_obj1 的锁为 B1, obj.sub_obj2 的锁为 B2 ....
这样,访问不同的子对象是可以并发的
然后在 Read/Close 中应该这样
Enter B1
Read obj.sub_obj1
Level B1
Enter B2
Read obj.sub_obj2
Level B2
...
如果觉得麻烦,可以
Enter B1
Enter B2
Enter B3
...
Read All
...
Level B3
Level B2
Level B1
因为 Read/Close 操作应该是比子对象的访问要少的多,这样对并发的影响也就小了
------解决思路----------------------
这个就比较麻烦了
你的总锁只负责增删是不行的,
假设某个线程1 取出了 map 里的某个 SUB_OBJ,准备进入 SUB_OBJ 的锁来访问它了,这时线程切换了,在另一个线程2 中要删除刚刚被取走的这个 SUB_OBJ, 它首先获得总锁,这个没问题,因为你的总锁不保护 SUB_OBJ 的访问,线程1 并没有触发总锁的; 然后它在获得 SUB_OBJ 的锁,这也没问题,因为线程1 正准备获取而还没有获取,于是线程 2 就把 SUB_OBJ 删除了。回到线程1 的时候访问这个被删除的对象行为就是不确定的了。
------解决思路----------------------
我的理解是,锁只要是沿这一个方向依赖的,比如A依赖B,B依赖C,或者反过来,就是不能两种都有
------解决思路----------------------
貌似case比较多:
1、Close和Read在同一线程中,但有多个线程在并发执行
2、Close和Read在两个不同的线程中
3、Close和Read在不同的线程中,n个Close Thread+m个Read Thread
总之:两个锁要慎用,用时要保持一致的先后顺序
------解决思路----------------------
请通读《Windows核心编程》!
------解决思路----------------------
第6章 线程的基础知识
第7章 线程的调度、优先级和亲缘性
第8章 用户方式中线程的同步
第9章 线程与内核对象的同步
第10章 线程同步工具包
第11章 线程池的使用