由《win32多线程程序设计》临界区的问题所想
之前看侯捷翻译的《win32多线程程序设计》中关于线程同步中的临界区问题,其中举得例子是对链表的操作。死锁的问题是对一个Swaplist函数的问题,现列举代码如下:
void SwapLists(List *list, List *list2)
{
List *tmp_list;
EnterCriticalSection(list1->critical_sec);
EnterCriticalSection(list2->critical_sec);
tmp->list = list1->head;
list1->head = list2->head;
list2->head = temp->list;
LeaveCriticalSection(list1->critical_sec);
LeaveCriticalSection(list2->critical_sec);
}
书中阐述如下:假设下面两次调用发生在不同线程的同一个时间点:
线程A SwapLists(home_address_list, work_address_list);
线程B SwapLists(work_address_list, home_address_list);
而在线程A的 SwapLists() 的第一次 EnterCriticalSection() 之后,发生了
context switch(译注:也就是调度程序选换了一个线程),然后线程B执行
了它的 SwapLists()操作,两个线程于是会落入“我等你,你等我”的轮回。
一直有一个问题问题:
假设线程A执行到第一次EnterCriticalSection()后,切换到了线程B。那么线程B走到第一次调用EnterCriticalSection(),由于线程A已经获得list1的临界区,
线程B走到list1就会等待。
但仔细一看才知道,线程A和线程B的list1和list2都是参数,在两个线程调用swaplist时可以相反的传入连个参数。
也正如例子所示:
线程A的参数调用顺序是:home_address_list, work_address_list
线程B的参数调用顺序是:work_address_list、home_address_list。
所以线程A进入home_address_list的临界区,然后切换到线程B进入到work_address_list的临界区。这样就形成死锁了。
由于看书不细心,或者知道到函数那一部分代码,很容易就只看到局部变量list1和list2。但是想要通过博客把这个问题写出来,这个过程就会细想或者仔细看一下,
于是就会把问题解决了。
其实,很多时候,写这些东西只是为了让自己能够更仔细、更清楚的了解问题所在。有事看书也懂了书中所讲的,但是面试的时候或者工作中解决问题还是不能够灵活应对,主要还是理解不够透彻。通过写博客,既能够训练自己把问题讲清楚,以便以后面试的时候能够应到入流,同时,也能加深自己的理解,工作中遇到问题能够下意识的考虑使用这些知识,这才算学以致用。
最新文章
- 破解版windows 7(旗舰版)下安装并使用vagrant统一开发环境
- 外网主机访问虚拟机下的web服务器(NAT端口转发)
- JavaScrip
- Spring学习笔记之整合hibernate
- NSURLSession的使用
- Android的Adapter用法
- Apache网站根目录
- Dubbo分布式服务框架入门
- Oracle VM VirtualBox虚拟机安装系统
- 控制反转(IOC)/依赖注入(DI)理解
- printf,sprintf,fprintf的比较
- Spring事务管理与数据库隔离级别的关系(Spring+mysql)
- C#版 - Leetcode 65. 有效数字 - 题解
- Failed to introspect annotated methods on class 异常
- springboot06-swagger2 自动化api文档
- JavaScript通过递归合并JSON
- nginx php
- C# NPOI生成Excel文档(简单样式)
- PHP使用UTF8编码读取ACCESS的乱码问题解决方案(转)
- Linux内核分析(第四周)
热门文章
- js获取url值
- JAVA基础知识之网络编程——-基于UDP协议的通信例子
- WITH (NOLOCK)
- ByteBuffer解析
- linux rc.sysinit文件详解
- 自动布局(Masonry)设置tabbar
- 首先,定义一个Print类,它有一个方法void output(int x),如果x的值是1,在控制台打印出大写的英文字母表;如果x的值是2,在 控制台打印出小写的英文字母表。其次,再定义一个主类——TestClass,在主类 的main方法中创建Print类的对象,使用这个对象调用方法output ()来打印出大 小写英文字母表。
- Android 基础
- Win7 winsock 注册表文件
- Systematic LncRNA Classification