之前看侯捷翻译的《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。但是想要通过博客把这个问题写出来,这个过程就会细想或者仔细看一下,

于是就会把问题解决了。

其实,很多时候,写这些东西只是为了让自己能够更仔细、更清楚的了解问题所在。有事看书也懂了书中所讲的,但是面试的时候或者工作中解决问题还是不能够灵活应对,主要还是理解不够透彻。通过写博客,既能够训练自己把问题讲清楚,以便以后面试的时候能够应到入流,同时,也能加深自己的理解,工作中遇到问题能够下意识的考虑使用这些知识,这才算学以致用。

最新文章

  1. 破解版windows 7(旗舰版)下安装并使用vagrant统一开发环境
  2. 外网主机访问虚拟机下的web服务器(NAT端口转发)
  3. JavaScrip
  4. Spring学习笔记之整合hibernate
  5. NSURLSession的使用
  6. Android的Adapter用法
  7. Apache网站根目录
  8. Dubbo分布式服务框架入门
  9. Oracle VM VirtualBox虚拟机安装系统
  10. 控制反转(IOC)/依赖注入(DI)理解
  11. printf,sprintf,fprintf的比较
  12. Spring事务管理与数据库隔离级别的关系(Spring+mysql)
  13. C#版 - Leetcode 65. 有效数字 - 题解
  14. Failed to introspect annotated methods on class 异常
  15. springboot06-swagger2 自动化api文档
  16. JavaScript通过递归合并JSON
  17. nginx php
  18. C# NPOI生成Excel文档(简单样式)
  19. PHP使用UTF8编码读取ACCESS的乱码问题解决方案(转)
  20. Linux内核分析(第四周)

热门文章

  1. js获取url值
  2. JAVA基础知识之网络编程——-基于UDP协议的通信例子
  3. WITH (NOLOCK)
  4. ByteBuffer解析
  5. linux rc.sysinit文件详解
  6. 自动布局(Masonry)设置tabbar
  7. 首先,定义一个Print类,它有一个方法void output(int x),如果x的值是1,在控制台打印出大写的英文字母表;如果x的值是2,在 控制台打印出小写的英文字母表。其次,再定义一个主类——TestClass,在主类 的main方法中创建Print类的对象,使用这个对象调用方法output ()来打印出大 小写英文字母表。
  8. Android 基础
  9. Win7 winsock 注册表文件
  10. Systematic LncRNA Classification