Gs Chen's blog


  • Home

  • Archives

  • Tags

  • Recommend

  • About

深入理解JVM之线程安全的实现方法(七)

Posted on 2017-02-26   |   In JVM   |     |   visitors

这篇文章算是对前面几篇文章的一个小结,从Java内存模型是如何来保证并发操作过程中的原子性、可见性以及有序性,到Happes-Before原则是如何保证内存模型中操作的有序性,再到我们特意分析了volatile和synchronized这两个JVM内置的实现同步机制关键字,在内存模型中的作用和他们的区别,但是这中间总是离不开「线程安全」几个字,那么实现线程安全的方法究竟有哪些,本文试图做一下总结。

线程安全的概念

周老师认为《Java Concurrency In Practice》的作者Brian Goetz对线程安全有个比较好的定义,如下:
当多个线程访问一个对象的时候,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象就是线程安全的。

Read more »

深入理解JVM之synchronized和Lock(六)

Posted on 2017-02-25   |   In JVM   |     |   visitors

在Java5.0之前,在协调对共享对象的访问时可以使用的机制只有synchronized和volatile。Java5.0增加了一种新的机制:ReentrantLock。与之前提到过的机制相反,ReentrantLock并不是一种替代内置加锁的方法,而是当内置加锁机制不适应时,作为一种可选的高级功能。

Read more »

深入理解JVM之volatile变量(五)

Posted on 2017-02-22   |   In JVM   |     |   visitors

关键字volatile可以说是java虚拟机提供的最轻量级的同步机制。当一个变量定义为volatile之后,它将具备两种特性,内存可见性和禁止重排序,至于后者在前一篇介绍先行发生原则中,其中有一条便是由volatile变量构成的原则,具体内容如下。

Read more »

深入理解JVM之先行发生关系(四)

Posted on 2017-02-22   |   In JVM   |     |   visitors

在网上搜了一下「先行发生原则」,发现大部分都是将周志明的那本深入理解Java虚拟机里面的内容抄下来的,并没有解释先行发生原则(Happens-before)到底是怎么回事,为什么会有这个东西。在理解Happens-before,我觉得有必要先知道指令重排序是怎么回事。

Read more »

Java8集合系列之ArrayBlockingQueue(九)

Posted on 2017-02-21   |   In Java Collection   |     |   visitors

上一篇是LinkedBlockingQueue,当中阐述了阻塞队列和非阻塞队列的区别。ArrayBlockingQueue也是一种阻塞队列,底层是以数组为数据结构,而且在初始化的时候必须指定容量上限。

Read more »

Java8集合系列之LinkedBlockingQueue(八)

Posted on 2017-02-20   |   In Java Collection   |     |   visitors

上一篇文章分析了ConcurrentLinkedQueue,实现了无限不定长的无锁并发的队列,线程安全。这篇文章则分析另外一种队列实现,线程安全的阻塞队列(BlockingQueue)。

阻塞队列浅析

阻塞队列与非阻塞队列

之前我们接触的linkedlist是非阻塞队列,LinkedList是双向链表,它实现了Dequeue接口。
使用非阻塞队列的时候有一个很大问题就是:它不会对当前线程产生阻塞,那么在面对类似消费者-生产者的模型时,就必须额外地实现同步策略以及线程间唤醒策略,这个实现起来就非常麻烦。
但是有了阻塞队列就不一样了,它会对当前线程产生阻塞,比如一个线程从一个空的阻塞队列中取元素,此时线程会被阻塞直到阻塞队列中有了元素。当队列中有元素后,被阻塞的线程会自动被唤醒(不需要我们编写代码去唤醒)。这样提供了极大的方便性。

Read more »

Java8集合系列之ConcurrentLinkedQueue(七)

Posted on 2017-02-17   |   In Java Collection   |     |   visitors

队列是一种经常被用到的数据结构,比如在生产者消费者场景中,简单则如一个链表实现,复杂则想kafka、rocketmq等等分布式消息队列。本文基于JDK1.8来分析java.util.concurrent包中的ConcurrentLinkedQueue,这个基于链表和CAS的并发优化的队列。

Read more »

Java8集合系列之Set(六)

Posted on 2017-02-16   |   In Java Collection   |     |   visitors

所有Set几乎都是内部用一个Map来实现, 因为Map里的KeySet就是一个Set,而value采用假值,全部使用同一个Object即可。

Read more »

深入理解JVM之CAS原子操作(九)

Posted on 2017-01-26   |   In JVM   |     |   visitors

在准备进入concurrentHashMap的源码世界中的时候,发现很多方法是基于CAS原子操作的,之前在看JVM的时候确实看过CAS,但是并没有仔细的去研究,所以决定先一探究竟,经过网上查阅一些资料,对CAS还是有了一些理解。

如果说在只有一个线程的时候,资源不会出现竞争,也不会存在所谓的共享资源的说法,很多问题可以避免,也无需讨论原子性操作的问题。但是当出现多个线程协调运行的时候,很多问题就会出现了,怎么提高多个线程访问共享资源的效率,如何避免多个线程并发读写共享资源时不出现数据混乱,这些问题都是在各个领域很经典的问题。

乐观锁与悲观锁

我们都知道,cpu是时分复用的,也就是把cpu的时间片,分配给不同的thread/process轮流执行,时间片与时间片之间,需要进行cpu切换,也就是会发生进程的切换。切换涉及到清空寄存器,缓存数据。然后重新加载新的thread所需数据。当一个线程被挂起时,加入到阻塞队列,在一定的时间或条件下,在通过notify(),notifyAll()唤醒回来。

Read more »

Java8集合系列之ConcurrentHashMap(五)

Posted on 2017-01-06   |   In Java Collection   |     |   visitors

Before JDK1.8版本

Hashtable

我们都知道HashMap是线程不安全的。Hashtable是线程安全的。看过Hashtable源码的我们都知道Hashtable的线程安全是采用在每个方法来添加了synchronized关键字来修饰,即Hashtable是针对整个table的锁定,这样就导致HashTable容器在竞争激烈的并发环境下表现出效率低下。翻阅Hashtable的源码,确实在put和get方法之前都添加了synchronized来完成同步操作,这样无论是在put还是get的时候只能同时进行一种操作,毫无疑问这种效率是极其低下的。

1
2
3
4
5
6
public synchronized V put(K key, V value) {
...
}
public synchronized V get(Object key) {
...
}

锁分离技术

基于Hashtable的缺点,人们就开始思考,假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率呢??这就是我们的“锁分离”技术,这也是ConcurrentHashMap实现的基础。

ConcurrentHashMap使用的就是锁分段技术,ConcurrentHashMap由多个Segment组成(Segment下包含很多Node,也就是我们的键值对了),每个Segment都有把锁来实现线程安全,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

Read more »
1234…6
Gs Chen

Gs Chen

Widen grain , Highten wall

58 posts
13 categories
38 tags
RSS
GitHub Weibo douban zhihu
Links
  • 江南白衣
© 2016 - 2018 Gs Chen
Powered by Hexo
Theme - NexT.Mist     |    您是本站第 位访客