文档章节

聊聊高并发(三)锁的一些基本概念

Original123
 Original123
发布于 2017/03/14 11:44
字数 1010
阅读 6
收藏 0

理解并发编程的一些基本概念很重要,给我们思考问题指明一个基本的方向。这篇说一说锁的一些基本概念。

在通常情况下我们说的锁都指的是“互斥”锁,因为在还存在一些特殊的锁,比如“读写锁”,不完全是互斥的。这篇文章说的锁专指互斥锁。

 

锁是处理并发的一种同步手段。单线程程序和并发程序的最终目的都是要保证程序的正确性,但是最大的区别是:

  • 单线程程序的正确性只关注程序的运行结果和目标是一致的
  • 并发程序的正确性除了运行结果正确外,还包含了活性的特性,所谓活性,指的就是程序无死锁,无饥饿

所以考察一个锁,也需要从三个方面考察:

1. 互斥性

2. 无死锁

3. 无饥饿

 

最简单的锁只保证互斥性,而互斥性本质上可以用一个布尔值表示,即一个二元状态。

互斥是保证并发程序正确性的一种特性,和互斥相关的一个专用名词就是临界区

临界区指的是“某个时刻仅能被一个线程执行的代码段”,也就是通常锁的被锁保护的代码段。

 

一个互斥锁的定义通常如下

 

[java] view plain copy

  1. interface Lock {  
  2.      public void lock();  
  3.      public void unlock();  
  4. }  


线程必须用指定的方式使用锁,lock动作必须在try块之前调用,如果lock在try里面执行,可能会在取到锁之前抛出异常,导致执行了unlock动作,从而发生错误。

 

熟悉Java显示锁的同学肯定知道使用ReentryLock就是如下的用法。

 

[java] view plain copy

  1. mutex.lock();  
  2. try{  
  3.  ...临界区  
  4. }finally{  
  5.     mutex.unlock()  
  6. }  


互斥意味着串行,也意味着等待。 这引出了著名的Amdahl定律

 

Amdahl定律: 即完成一个工作能获得的加速比,受限于这个工作中必须被串行的部分。(通常串行部分都是因为被互斥锁保护了)

加速比的定义是一个处理器完成一个工作的时间和采用n个处理器并发完成该工作的时间比。

 

[java] view plain copy

  1. Amdahl定律给出的加速比如下  
  2.   
  3. S = 1 / ( 1 - p + p/n)  
  4.   
  5. S为加速比  
  6. 1为完成工作的时间  
  7. p指可以并行的部分  
  8. n指处理器个数  


从Amdahl定律可以看出,串行的工作越多,获得的加速比就越小。

 

Amdahl给我们编程实际启示有:

1. 尽量减小互斥锁的粒度,锁粒度越小表示串行的部分越少

2. 能不用锁,就不要用锁。不用锁表示串行的部分越少

 

接下来说说活性相关的概念。

死锁意味者系统冻结最终相关的所有线程都永久地停滞等待。

饥饿则是总有一些线程能够运行一小部分线程永久停滞等待

 

所以无饥饿意味着肯定无死锁。但是无死锁不意味着无饥饿。

 

《多处理器编程的艺术》一书中给出了几种锁的实现,其中Peterson算法可以保证两个线程使用锁的时候锁具备互斥,无死锁,无饥饿特性。

 

[java] view plain copy

  1. class Peterson implements Lock {  
  2.      private boolean[] flag = new boolean[2];  
  3.      private int victim;  
  4.      public void lock(){  
  5.            int i = ThreadID.get();  
  6.            int j = 1 - i;  
  7.            flag[i]= true;  // 保证两个线程先后运行不死锁,实现互斥   
  8.            victim = i;  // 保证两个线程同时运行时不死锁,实现互斥  
  9.            while(flag[j] && victim == i){}  // 互斥意味着等待  
  10.      }  
  11.   
  12.      public void unlock(){  
  13.            int i = ThreadID.get();  
  14.            flag[i] = false;  
  15.     }  
  16.   
  17. }  


Bakery锁支持n个线程的互斥协议。通过数学证明了:

 

n线程的无死锁互斥算法需要n个不同的存储单元(变量)来保存中间状态。

© 著作权归作者所有

Original123
粉丝 7
博文 66
码字总数 87205
作品 0
徐汇
架构师
私信 提问
聊聊并发(十四)—基于AQS实现互斥信号(BooleanMutex)

并发系列 聊聊并发(一)深入分析Volatile的实现原理 聊聊并发(二)Java SE1.6中的Synchronized 聊聊并发(三)Java线程池的分析和使用 聊聊并发(四)深入分析ConcurrentHashMap 聊聊并发(...

陶邦仁
2015/11/22
342
1
探究Java的ConcurrentHashMap实现机制

原文地址: http://blog.csdn.net/u011080472/article/details/51392712 在学习ConcurrentHashMap的高并发时,找到了一些高质量的博客,就没有重复转载了。分别列出了JDK6中的Segment分段加锁...

Gavin__Zhou
2017/08/06
0
0
聊聊并发(十三)—AQS框架深入分析

并发系列 聊聊并发(一)深入分析Volatile的实现原理 聊聊并发(二)Java SE1.6中的Synchronized 聊聊并发(三)Java线程池的分析和使用 聊聊并发(四)深入分析ConcurrentHashMap 聊聊并发(...

陶邦仁
2015/11/20
460
0
第一次面试题

JMM,高并发高吞吐使用的GC方法,如何造成OOM,解决OOM 聊聊集合hashmap,ArrayList,concurrenthashmap 锁的分类 java中队列,树数据结构的实现 springboot分布式 redis基本数据结构,跳表 mysql验...

芥末无疆sss
2017/12/29
0
0
[原创]商城系统下单库存管控系列杂记(二)(并发安全和性能部分延伸)

商城系统下单库存管控系列杂记(二)(并发安全和性能部分延伸) 前言 参与过几个中小型商城系统的开发,随着时间的增长,以及对系统的深入研究和测试,发现确实有很多值得推敲和商榷的地方(...

autumnbing
2017/11/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

程序设计基础(C)第06讲例程

1summing.c /* summing.c -- 根据用户键入的整数求和 */#include <stdio.h>int main(void){ long num; long sum = 0L; /* 把sum 初始化为0 */ int status; p......

树人大学数字媒体吴凡
24分钟前
6
0
聊聊nacos config的publishConfig

序 本文主要研究一下nacos config的publishConfig ConfigController nacos-1.1.3/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java @Controller@R......

go4it
51分钟前
5
0
Eureka应用注册与集群数据同步源码解析

在之前的EurekaClient自动装配及启动流程解析一文中我们提到过,在构造DiscoveryClient类时,会把自身注册到服务端,本文就来分析一下这个注册流程 客户端发起注册 boolean register() t...

Java学习录
今天
11
0
Java描述设计模式(15):责任链模式

本文源码:GitHub·点这里 || GitEE·点这里 一、生活场景描述 1、请假审批流程 公司常见的请假审批流程:请假天数 当 day<=3 天,项目经理审批当 3<day<=5 天,部门经理审批当 day>5 天...

知了一笑
今天
10
0
总结:数组与链表

1、内存申请:数组在内存上是连续的空间;链表,内存地址上可以是不连续的。 2、查询速度:数组可以随机访问,链表必须顺序访问,即从首个元素开始遍历,逐个查找,所以数组查询很快。 3、写入...

浮躁的码农
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部