`

Java多线程三(线程安全的集合及java.util.concurrent包的锁)

阅读更多

一、线程安全的集合

        JDK1.5之前,可以使用Venctor和Hashtable,也可以由java.util.Collections来创建线程安全的集合,如:Connections.synchronizedSet(Set<T>); Connections.synchronizedList(List<T>);Connections.synchronizedMap(Map<K, V>)等,其简单的原理是每个方法都增加了synchronized来保证线程安全。

JDK1.5之后,提供了java.util.concurrent并发包,它提供的新集合类允许通过在语义中的少量更改来获得更高的并发。

  • CopyOnWriteArrayList 其中的set、add、remove等方法,都使用了ReentrantLock的lock()来加锁,unlock()来解锁。当增加元素的时候使用Arrays.copyOf()来拷贝副本,在副本上增加元素,然后改变原引用指向副本。
  • CopyOnWriteArraySet 使用了CopyOnWriteArrayList来存储数据,remove方法调用CopyOnWriteArrayList的remove方法。add方法调用了CopyOnWriteArrayList的addIfAbsent方法,addIfAbsent同样使用了ReentrantLock的lock()来加锁,unlock()来解锁。 
  • ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术。它使用了多个锁来控制对hash表的不同部分进行的修改。ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的hash table,它们有自己的锁(由ReentrantLock来实现的)。只要多个修改操作发生在不同的段上,它们就可以并发进行。

二、 java.util.concurrent包的锁

 

锁定和原子之Lock

    Java 语言内置了锁定工具 -- synchronized 关键字。当线程获得监视器时(内置锁定),其他线程如果试图获得相同锁定,那么它们将被阻塞,直到第一个线程释放该锁定。同步还确保随后获得相同锁定的线程可以看到之前的线程在具有该锁定时所修改的变量的值,从而确保如果类正确地同步了共享状态的访问权,那么线程将不会看到变量的"失效"值,这是缓存或编译器优化的结果。

    虽然同步没有什么问题,但它有一些限制,在一些高级应用程序中会造成不便。Lock 接口将内置监视器锁定的锁定行为普遍化,允许多个锁定实现,同时提供一些内置锁定缺少的功能,如计时的等待、可中断的等待、锁定轮询、每个锁定有多个条件等待集合以及无阻塞结构的锁定。

public interface Lock {
    void lock();
    void lockInterruptibly() throws InterruptedException;
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    void unlock();
    Condition newCondition();
}

 ReentrantLock

    ReentrantLock 是具有与隐式监视器锁定(使用 synchronized 方法和语句访问)相同的基本行为和语义的 Lock 的实现,但它具有扩展的能力。

    作为额外收获,在竞争条件下,ReentrantLock 的实现要比现在的 synchronized 实现更具有可伸缩性。(有可能在 JVM 的将来版本中改进 synchronized 的竞争性能。)

    这意味着当许多线程都竞争相同锁定时,使用 ReentrantLock 的吞吐量通常要比 synchronized 好。换句话说,当许多线程试图访问 ReentrantLock 保护的共享资源时,JVM 将花费较少的时间来调度线程,而用更多个时间执行线程。

    虽然 ReentrantLock 类有许多优点,但是与同步相比,它有一个主要缺点 -- 它可能忘记释放锁定。建议当获得和释放 ReentrantLock 时使用下列结构:

Lock lock = new ReentrantLock();
//...
lock.lock();
try {
  // perform operations protected by lock
}
catch(Exception ex) {
 // restore invariants
}finally {
  lock.unlock();
}

 Condition

    就像 Lock 接口是同步的具体化,Condition 接口是 Object 中 wait() 和 notify() 方法的具体化。Lock 中的一个方法是 newCondition(),它要求锁定向该锁定返回新的 Condition 对象限制。await()、signal() 和 signalAll() 方法类似于 wait()、notify() 和 notifyAll(),但增加了灵活性,每个 Lock 都可以创建多个条件变量。这简化了一些并发算法的实现。

ReadWriteLock

    ReentrantLock 实现的锁定规则非常简单 -- 每当一个线程具有锁定时,其他线程必须等待,直到该锁定可用。有时,当对数据结构的读取通常多于修改时,可以使用更复杂的称为读写锁定的锁定结构,它允许有多个并发读者,同时还允许一个写入者独占锁定。该方法在一般情况下(只读)提供了更大的并发性,同时在必要时仍提供独占访问的安全性。ReadWriteLock 接口和 ReentrantReadWriteLock 类提供这种功能 -- 多读者、单写入者锁定规则,可以用这种功能来保护共享的易变资源。

 

三、原子变量

    即使大多数用户将很少直接使用它们,原子变量类(AtomicInteger、AtomicLong、AtomicReference 等等)也有充分理由是最显著的新并发类。这些类公开对 JVM 的低级别改进,允许进行具有高度可伸缩性的原子读-修改-写操作。大多数现代 CPU 都有原子读-修改-写的原语,比如比较并交换(CAS)或加载链接/条件存储(LL/SC)。原子变量类使用硬件提供的最快的并发结构来实现。

    许多并发算法都是根据对计数器或数据结构的比较并交换操作来定义的。通过暴露高性能的、高度可伸缩的 CAS 操作(以原子变量的形式),用 Java 语言实现高性能、无等待、无锁定的并发算法已经变得可行。

    几乎 java.util.concurrent 中的所有类都是在 ReentrantLock 之上构建的,ReentrantLock 则是在原子变量类的基础上构建的。所以,虽然仅少数并发专家使用原子变量类,但 java.util.concurrent 类的很多可伸缩性改进都是由它们提供的。

    原子变量主要用于为原子地更新"热"字段提供有效的、细粒度的方式,"热"字段是指由多个线程频繁访问和更新的字段。另外,原子变量还是计数器或生成序号的自然机制。

 

 参考博文:

java.util.concurrent介绍 

ConcurrentHashMap之实现细节

 

 

 

分享到:
评论

相关推荐

    Java高性能线程库(java.util.concurrent包的补充)

    一个高性能的Java线程库,该库是 JDK 1.5 中的 java.util.concurrent 包的补充,可用于基于并发消息机制的应用。该类库不提供远程的消息功能,其设计的宗旨是实现一个内存中的消息传递机制. 主要特点有: * All ...

    java.util.concurrent-多线程框架.docx

    java.util.concurrent-多线程框架

    java多线程学习-java.util.concurrent详解(一) Latch/Barrier

    NULL 博文链接:https://janeky.iteye.com/blog/769965

    java.util.concurrent_您不知道的5件事

    除了具有很好的并发性的Collections,java.util.concurrent还引入了其他一些预先构建的组件,它们可帮助您调整和执行多线程应用程序中的线程。

    java 多线程同步

    java.util.concurrent 包含许多线程安全、测试良好、高性能的并发构建块。不客气地说,创建 java.util.concurrent 的目的就是要实现 Collection 框架对数据结构所执行的并发操作。通过提供一组可靠的、高性能并发...

    java多线程并发编程例子

    关于java.util.concurrent多线程核心包内各种线程资源的使用场景例子

    Redis客户端Redisson.zip

    java.util.concurrent.CountDownLatch通过org.redisson.core.RTopic 实现分布式订阅/发布通过 org.redisson.core.RHyperLogLog 实现分布式HyperLogLog 线程安全支持 OSGi超过110个单元测试 标签:Redisson...

    JAVA_API1.6文档(中文)

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

    图解java多线程设计模式

    java.util.concurrent包、synchronized关键字、Swing框架、Java内存模型等内容也均有涉及,不仅能够了解Java多线程的相关知识,还可加深对Java语言的理解。 本书适合以下读者阅读 a.对多线程感兴趣的人 b.对Java...

    java核心知识点整理.pdf

    25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................

    Java基础[04-集合框架].ppt

    集合可以看作是一种容器,用来存储对象信息。所有集合类都位于java.util包下,但支持多线程的集合类位于java.util.concurrent包下。

    多线程,高并发.pdf

    1. stop() 和 suspend() 方法为何不推荐使用? 2. sleep() 和 wait() 有什么区别? 3. 同步和异步有何异同,...5. 简述 synchronized 和 java.util.concurrent.locks.Lock 的异同? 6. 概括的解释下线程的几种可用状态。

    JAVA核心知识点整理(有效)

    25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................

    Java多线程Callable接口

    Runnable是执行工作的独立任务,但是它不返回任何值,如果你希望任务在完成时能够返回一个值,那么可以实现... import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import j

    Java基础知识点总结.docx

    无论是工作学习,不断的总结是必不可少的。只有不断的总结,发现问题,弥补不足,才能长久的...java.util.concurrent.locks包下常用的类 326 NIO(New IO) 327 volatile详解 337 Java 8新特性 347 Java 性能优化 362

    Java 1.6 API 中文 New

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR ...

    java 并发编程 多线程

    java 并发 编程 多线程 concurrent lock condition executorserice executor java.util.curcurrent.

    Java 面试宝典

    1、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? ...... 7 2、Java 有没有 goto? .......................................................................................................

    基于Java多线程同步的安全性研究

    解决Java多线程同步的方法是在需要同步的方法签名中加入synchronized关键字,使用synchronized对需要进行同步的代码段进行同步,或使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象。为解决多个线程对同一...

    java api最新7.0

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR ...

Global site tag (gtag.js) - Google Analytics