Java 并发核心编程
内容涉及:
1、关于java并发
2、概念
3、保护共享数据
4、并发集合类
5线程
6、线程协作及其他
1、关于java并发
自从java创建以来就已经支持并发的理念,如线程和锁。这篇指南主要是为帮助java多线程开发人员理解并发的核心概念以及如何应用这些理念。本文的主题是关于具有java语言风格的Thread、synchronized、volatile,以及J2SE5中新增的概念,如锁(Lock)、原子性(Atomics)、并发集合类、线程协作摘要、Executors。开发者通过这些基础的接口可以构建高并发、线程安全的java应用程序。
2、概念
本部分描述的java并发概念在这篇DZone Refard会被通篇使用。
从JVM并发看CPU内存指令重排序(Memory Reordering):http://kenwublog.com/illustrate-memory-reordering-in-cpu
java内存模型详解: http://kenwublog.com/explain-java-memory-model-in-detail
概念
|
描述
|
Java Memory Model
Java内存模型
|
在JavaSE5(JSR133)中定义的Java Memory Model(JMM)是为了确保当编写并发代码的时候能够提供Java程序员一个可用的JVM实现。术语JMM的作用类似与一个观察同步读写字段的monitor。它按照“happens-before order(先行发生排序)”的顺序—可以解释为什么一个线程可以获得其他线程的结果,这组成了一个属性同步的程序,使字段具有不变性,以及其他属性。
|
monitor
Monitor
|
Java语言中,每个对象都拥有一个访问代码关键部分并防止其他对象访问这段代码的“monitor”(每个对象都拥有一个对代码关键部分提供访问互斥功能的“monitor”)。这段关键部分是使用synchronized对方法或者代码标注实现的。同一时间在同一个monitor中,只允许一个线程运行代码的任意关键部分。当一个线程试图获取代码的关键部分时,如果这段代码的monitor被其他线程拥有,那么这个线程会无限期的等待这个monitor直到它被其他线程释放。除了访问互斥之外,monitor还可以通过wait和notify来实现协作。
|
原子字段赋值
Atomic field assignment
|
除了doubles和langs之外的类型,给一个这些类型的字段赋值是一个原子操作。在JVM中,doubles和langs的更新是被实现为2个独立的操作,因此理论上可能会有其他的线程得到一个部分更新的结果。为了保护共享的doubles和langs,可以使用volatile标记这个字段或者在synchronized修饰的代码块中操作字段。
|
竞争状态
Race condition
|
竞争发生在当不少于一个线程对一个共享的资源进行一系列的操作,如果这些线程的操作的顺序不同,会导致多种可能的结果。
|
数据竞争
Data race
|
数据竞争主要发生在多个线程访问一个共享的、non-final、non-volatile、没有合适的synchronization限制的字段。Java内存模型不会对这种非同步的数据访问提供任何的保证。在不同的架构和机器中数据竞争会导致不可预测的行为。
|
安全发布
Safe publications
|
在一个对象创建完成之前就发布它的引用时非常危险的。避免这种使用这种引用的一种方法就是在创建期间注册一个回调接口。另外一种不安全的情况就是在构造子中启动一个线程。在这2种情况中,非完全创建的对象对于其他线程来说都是可见的。
|
不可变字段
Final Fields
|
不可变字段在对象创建之后必须明确设定一个值,否则编译器就会报出一个错误。一旦设定值后,不可变字段的值就不可以再次改变。将一个对象的引用设定为不可变字段并不能阻止这个对象的改变。例如,ArrayList类型的不可变字段不能改变为其他ArrayList实例的引用,但是可以在这个list实例中添加或者删除对象。
在创建结尾,对象会遇到”final field freeze”:如果对象被安全的发布后,即使在没有synchronization关键字修饰的情况下,也能保证所有的线程获取final字段在构建过程中设定的值。final field freezer不仅对final字段有用,而且作用于final对象中的可访问属性。
|
不可变对象
Immutable objects
|
在语法上final 字段能够创建不需要synchronization修饰的、能够被共享读取的线程安全的不可变对象。实现Immutable Object需要保证如下条件:
·对象被安全的发布(在创建过程中this 引用是无法避免的)
·所有字段被声明为final
·在创建之后,在对象字段能够被访问的范围中是不允许修改这个字段的。
·class被声明为final(为了防止subclass违反这些规则)
|
3、保护共享数据
编写线程安全的java程序,当修改共享数据的时候要求开发人员使用合适的锁来保护数据。锁能够建立符合Java Memory Model要求的访问顺序,而且确保其他线程知道数据的变化。
注意:
在Java Memory Model中,如果没有被synchronization修饰,改变数据不需要什么特别的语法表示。JVM能够自由地重置指令顺序的特性和对可见性的限制方式很容易让开发人员感到奇怪。
3.1、Synchronized
每个对象实例都拥有一个每次只能让一个线程锁住的monitor。synchronized能够用在一个方法或者代码块中来锁住这个monitor。用synchronized修饰一个对象,当修改这个对象的一个字段,synchronized保证其他线程余下的对这个对象的读操作能够获取修改后的值。需要注意的是修改同步块之外的数据或者synchronized没有修饰当前被修改的对象,那么不能保证其他线程读到这些最新的数据。synchronized关键字能够修饰一个对象实例中的函数或者代码块。在一个非静态方法中this关键字表示当前的实例对象。在一个synchronized修饰的静态的方法中,这个方法所在的类使用Class作为实例对象。
3.2、Lock
Java.util.concurrent.locks包中有个标准Lock接口。ReentrantLock 实现了Lock接口,它完全拥有synchronized的特性,同时还提供了新的功能:获取Lock的状态、非阻塞获取锁的方法tryLock()、可中断Lock。
下面是使用ReentrantLock的详细示例:
public class Counter{
private final Lock lock = new ReentrantLock();
private int value;
public int increment() {
lock.lock();
try {
return ++value;
}finally{
lock.unlock();
}
}
}
|
3.3、ReadWriteLock
Java.util.concurrent.locks包中还有个ReadWriteLock接口(实现类是ReentrantWriteReadLock),它定义一对锁:读锁和写锁,特征是能够被并发的读取但每次只能有一个写操作。使用ReentrantReadWriteLock并发读取特性的详细示例:
public class ReadWrite {
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private int value;
public void increment(){
lock.writeLock().lock();
try{
value++;
}finally{
lock.writeLock().lock();
}
}
public int current(){
lock.readLock().lock();
try{
return value;
}finally{
lock.readLock().unlock();
}
}
}
|
3.4、volatile
volatile原理与技巧: http://kenwublog.com/the-theory-of-volatile
volatile修饰符用来标注一个字段,表明任何对这个字段的修改都必须能被其他随后访问的线程获取到,这个修饰符和同步无关。因此,volatile修饰的数据的可见性和synchronization类似,但是这个它只作用于对字段的读或写操作。在JavaSE5之前,因为JVM的架构和实现的原因,不同JVM的volatile效果是不同的而且也是不可信的。下面是Java内存模型明确地定义volatile的行为:
public class Processor implements Runnable {
private volatile boolean stop;
public void stopProcessing(){
stop = true;
}
public void run() {
while (!stop) {
//do processing
}
}
}
|
注意:使用volatile修饰一个数组并不能让这个数组的每个元素拥有volatile特性,这种声明只是让这个数组的reference具有volatile属性。数组被声明为AtomicIntegerArray类型,则能够拥有类似volatile的特性。
3.5、原子类
使用volatile的一个缺点是它能够保证数据的可见性,却不能在一个原子操作中对volatile修饰的字段同时进行校验和更新操作。java.util.concurrent.atomic包中有一系列支持在单个非锁定(lock)的变量上进行原子操作的类,类似于volatile。示例:
public class Counter{
private AtomicInteger value = new AtomicInteger();
private int value;
public int increment() {
return value.incrementAndGet();
}
}
|
incrementAndGet方法是原子类的复合操作的一个示例。booleans, integers, longs, object references, integers数组, longs数组, object references数组 都有相应的原子类。
3.6、ThreadLocal
通过ThreadLocal能数据保存在一个线程中,而且不需要lock同步。理论上ThreadLocal可以让一个变量在每个线程都有一个副本。ThreadLocal常用来屏蔽线程的私有变量,例如“并发事务”或者其他的资源。而且,它还被用来维护每个线程的计数器,统计,或者ID生成器。
public class TransactionManager {
private static final ThreadLocal<Transaction> currentTransaction
= new ThreadLocal<Transaction>() {
@Override
protected Transaction initialValue() {
return new NullTransaction();
}
};
public Transaction currentTransaction() {
font-size: 13pt; color: #f0dfaf; font-family
分享到:
Global site tag (gtag.js) - Google Analytics
|
相关推荐
62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java...
Java 多线程与并发理论基础 Java 多线程与并发是 Java 编程语言中的一种机制,用于提高程序的执行效率和响应速度。多线程的出现是为了解决 CPU、内存、I/O 设备速度差异的问题,通过分时复用 CPU、缓存和进程、...
Java并发编程实践-电子书-01章.pdf Java并发编程实践-电子书-02章.pdf Java并发编程实践-电子书-03章.pdf Java并发编程实践-电子书-04章.pdf Java并发编程实践-电子书-05章.pdf Java并发编程实践-电子书-06章.pdf ...
Java并发编程---synchronized关键
Java并发编程中的多线程协作机制 在 Java 并发编程中,多线程协作机制是非常重要的一部分。多线程协作机制是指在多线程编程中,多个线程之间如何协作、同步和通信,以达到共同完成某个任务的目的。Java 提供了多种...
《Java并发编程实战》是Java并发编程领域的一本经典著作,它深入浅出地介绍了如何在Java平台上进行高效的多线程编程。这本书的源码提供了丰富的示例,可以帮助读者更好地理解书中的理论知识并将其应用到实际项目中。...
Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。以下是对标题和描述中所提及的几个知识点的详细解释: 1. **线程与并发** - **线程*...
《Java并发编程实战》这本书是关于Java语言中并发编程技术的经典著作。它详细介绍了如何在Java环境中有效地实现多线程程序和并发控制机制。在Java平台上,由于其本身提供了强大的并发编程支持,因此,掌握并发编程...
这份"java-java面试题库整理-基础-JVM-线程并发-框架等.zip"文件提供了一个全面的复习资源,帮助求职者准备Java相关的面试。 1. **Java基础知识** - 类与对象:Java是一种面向对象的语言,了解类的定义、构造器、...
Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。阿里大牛梁飞编写的《Java并发编程常识》PPT,深入浅出地讲解了这个主题,对开发者来...
《JAVA并发编程艺术》是Java开发者深入理解和掌握并发编程的一本重要著作,它涵盖了Java并发领域的核心概念和技术。这本书详细阐述了如何在多线程环境下有效地编写高效、可靠的代码,对于提升Java程序员的技能水平...
### Java并发编程实战知识点概述 #### 一、Java并发特性详解 在《Java并发编程实战》这本书中,作者深入浅出地介绍了Java 5.0和Java 6中新增的并发特性。这些特性旨在帮助开发者更高效、安全地编写多线程程序。书中...
Java并发编程是软件开发中的重要领域,特别是在大型系统和高并发场景中不可或缺。"13-Java并发编程学习宝典.zip" 包含了一系列关于Java并发编程的学习资源,旨在帮助开发者掌握多线程编程的核心技术和最佳实践。以下...
《Java并发编程艺术》这本书深入探讨了Java平台上的并发编程技术。并发编程是现代多核处理器环境下提升软件性能的关键手段,而Java语言提供了丰富的工具和API来支持这一领域。本书旨在帮助开发者理解和掌握如何在...
Java并发编程实践是Java开发中不可或缺的一个领域,它涉及到如何高效、正确地处理多线程环境中的任务。这本书的读书笔记涵盖了多个关键知识点,旨在帮助读者深入理解Java并发编程的核心概念。 1. **线程和进程的...
《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南。这本书旨在帮助开发者理解和掌握在Java环境中创建高效、可扩展且可靠的多线程应用程序的关键技术和实践。它涵盖了从基本概念到高级主题的广泛内容,...
《JAVA并发编程实践》是Java开发人员深入理解并发编程的一本经典著作,由Doug Lea撰写,本书中文版高清完整,包含丰富的书签,便于读者查阅和学习。这本书旨在帮助开发者掌握在Java平台上进行高效、安全并发编程的...
求职者需要了解如何避免死锁,掌握线程池的工作原理,以及Java并发编程的基本原则。 数据库方面,"数据库.pdf"可能涉及SQL优化、索引原理、事务处理、存储过程、数据库设计范式等主题。对于MySQL,可能还会探讨...