码农翻身之我是一个线程 --- 读书笔记

码农翻身之我是一个线程

1. "我"的宿命 ----> 处理包裹

1.1 计算机世界规则

  1. 不知何时被选中执行任务
  2. 执行过程中随时可能被打断
  3. 有硬盘、数据库等耗时操作需要让出CPU等待
  4. 数据来了也得等CPU挑选

1.2 "我"的处理流程图

"我"的处理流程图

2. "我"的小伙伴们

  1. Memcached 线程: 分布式缓存用户数据
  2. 数据库连接线程: 他们也有一个线程池

3. "锁"出的问题

3.1 存取款操作需加锁后执行,例如:

1 没加锁时操作情况

线程1:存入300元 线程2:取出200元
获取当前余额:1000 ——
计算最新余额:1000 + 300 = 1300 ——
线程中断,等待下次系统挑中执行 ——
—— 获取当前余额:1000
—— 计算最新余额:1000 - 200 = 800
—— 线程中断,等待下次被系统挑中执行
再次执行,更新余额:1300 ——
—— 再次执行,更新余额:800 (存的钱丢了)

2 加锁时操作情况

线程1:存入300元 线程2:取出200元
获取账户A的锁:成功 ——
获取当前余额:1000 ——
计算最新余额:1000 + 300 = 1300 ——
线程中断,等待下次系统挑中执行 ——
—— 获取账户A的锁:失败,进入阻塞状态
被系统选中,更新余额:1300 ——
释放账户A的锁 ——
—— 获取账户A的锁:成功
—— 获取当前余额:1300
—— 计算最新余额:1300 - 200 = 1100
—— 更新余额:1100
—— 释放账户A的锁

3.2 死锁的发生

见下图:

线程1:演员 -> 导演 线程2:导演 -> 演员
获取演员的锁:成功 ——
线程中断,等待下次系统挑中执行 ——
—— 获取导演的锁:成功
—— 线程中断,等待下次系统挑中执行
获取导演的锁:失败,继续等待 ——
—— 获取演员的锁:失败,继续等待

最终只好干掉一个线程,来保证正常执行

3.3 死锁的解决:新规则

至此,新建立一个规则:获取资源的锁之前,必须先让所有资源统一进入一个算法,计算资源的优先级;并且永远按照从小到大的方式获取锁。如下表所示:

PS: 这里假设导演的优先级大于演员的优先级

线程1:演员 -> 导演 线程2:导演 -> 演员
获取导演的锁:成功 ——
线程中断,等待下次系统挑中执行 ——
—— 获取导演的锁:失败,继续等待
获取演员的锁:成功 ——
执行转账 ——
释放演员的锁 ——
释放导演的锁 ——
—— 获取导演的锁:成功
—— 获取演员的锁:成功
—— 执行转账
—— 释放演员的锁
—— 释放导演的锁
注意:1. 释放锁的时候最好是从优先级小的资源开始释放
     2. 所谓优先级的大小,实际就是将该资源变成一个数来比较,例如,用字符串的hashcode来比较。

后续内容更加精彩,江湖再见~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章