`
footman265
  • 浏览: 118420 次
  • 性别: Icon_minigender_1
  • 来自: 宁波
社区版块
存档分类
最新评论

Java 并发核心编程(一)

    博客分类:
  • j2SE
阅读更多

 

Java 并发核心编程

内容涉及:

1、关于java并发

2、概念

3、保护共享数据

4、并发集合类

5线程

6、线程协作及其他

 

1、关于java并发

自从java创建以来就已经支持并发的理念,如线程和锁。这篇指南主要是为帮助java多线程开发人员理解并发的核心概念以及如何应用这些理念。本文的主题是关于具有java语言风格Threadsynchronizedvolatile以及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内存模型

JavaSE5JSR133)中定义的Java Memory ModelJMM)是为了确保当编写并发代码的时候能够提供Java程序员一个可用的JVM实现。术语JMM的作用类似与一个观察同步读写字段的monitor。它按照“happens-before order(先行发生排序)”的顺序—可以解释为什么一个线程可以获得其他线程的结果,这组成了一个属性同步的程序,使字段具有不变性,以及其他属性。

monitor

Monitor

Java语言中,每个对象都拥有一个访问代码关键部分并防止其他对象访问这段代码的“monitor”(每个对象都拥有一个对代码关键部分提供访问互斥功能的“monitor”)。这段关键部分是使用synchronized对方法或者代码标注实现的。同一时间在同一个monitor中,只允许一个线程运行代码的任意关键部分。当一个线程试图获取代码的关键部分时,如果这段代码的monitor被其他线程拥有,那么这个线程会无限期的等待这个monitor直到它被其他线程释放。除了访问互斥之外,monitor还可以通过waitnotify来实现协作。

原子字段赋值

Atomic field assignment

除了doubleslongs之外的类型,给一个这些类型的字段赋值是一个原子操作。在JVM中,doubleslongs的更新是被实现为2个独立的操作,因此理论上可能会有其他的线程得到一个部分更新的结果。为了保护共享的doubleslongs,可以使用volatile标记这个字段或者在synchronized修饰的代码块中操作字段。

竞争状态

Race condition

竞争发生当不少于一个线程对一个共享的资源进行一系列的操作,如果这些线程的操作的顺序不同,会导致多种可能的结果。

数据竞争

Data race

数据竞争主要发生在多个线程访问一个共享的、non-finalnon-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.1Synchronized

每个对象实例都拥有一个每次只能让一个线程锁住的monitorsynchronized能够用在一个方法或者代码块中来锁住这个monitor。用synchronized修饰一个对象,当修改这个对象的一个字段,synchronized保证其他线程余下的对这个对象的读操作能够获取修改后的值。需要注意的是修改同步块之外的数据或者synchronized没有修饰当前被修改的对象,那么不能保证其他线程读到这些最新的数据synchronized关键字能够修饰一个对象实例中的函数或者代码块。在一个非静态方法中this关键字表示当前的实例对象。在一个synchronized修饰的静态的方法中,这个方法所在的类使用Class作为实例对象。

 

3.2Lock

Java.util.concurrent.locks包中有个标准Lock接口。ReentrantLock 实现了Lock接口,它完全拥有synchronized的特性,同时还提供了新的功能:获取Lock的状态、非阻塞获取锁的方法tryLock()、可中断Lock

下面是使用ReentrantLock的详细示例:

 

private final Lock lock = new ReentrantLock();
   private int value; 
   public int increment() {
   lock.lock();
   try {
      return ++value;
   }finally{
      lock.unlock();
   }
  }
}
  

 

 

3.3ReadWriteLock

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().unlock();
   }
  }
public int current(){
   lock.readLock().lock();
   try{
   return value;
   }finally{
       lock.readLock().unlock();
   }
  }
}
 

 

3.4volatile

volatile原理与技巧http://kenwublog.com/the-theory-of-volatile

volatile修饰符用来标注一个字段,表明任何对这个字段的修改都必须能被其他随后访问的线程获取到,这个修饰符和同步无关。因此,volatile修饰的数据的可见性和synchronization类似,但是这个它只作用于对字段的读或写操作。在JavaSE5之前,因为JVM的架构和实现的原因,不同JVMvolatile效果是不同的而且也是不可信的。下面是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.6ThreadLocal

通过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() {
Transaction current = currentTransaction.get();
if(current.isNull()) {
current = new TransactionImpl();
currentTransaction.put(current);
}
return current;
}
}
   

 


 

分享到:
评论

相关推荐

    Java 并发核心编程

    ### Java 并发核心编程知识点解析 #### 一、Java并发概述 自Java诞生之初,其设计者就赋予了该语言强大的并发处理能力。Java语言内置了对线程和锁的支持,这使得开发者能够轻松地编写多线程应用程序。本文旨在帮助...

    Java并发核心编程.pdf

    Java并发核心编程.pdf

    Java并发编程-3.pdf

    Java并发编程中的多线程协作机制 在 Java 并发编程中,多线程协作机制是非常重要的一部分。多线程协作机制是指在多线程编程中,多个线程之间如何协作、同步和通信,以达到共同完成某个任务的目的。Java 提供了多种...

    Java 并发核心编程原文+译文

    Java并发核心编程是Java开发中的重要领域,它涉及到多线程和高效率程序设计的关键技术。在Java 5和Java 6中,JVM引入了大量的并发工具和改进,以支持多处理器和多核系统上的高性能应用程序。以下是这些知识点的详细...

    《java 并发编程实战高清PDF版》

    在Java并发编程中,多线程是核心概念之一。多线程允许程序同时执行多个任务,从而充分利用系统资源,提高程序性能。然而,多线程编程也带来了同步和竞态条件等问题,这需要开发者具备良好的线程管理和同步机制的知识...

    java并发核心编程

    ### Java并发核心编程 #### 一、关于Java并发 自Java问世以来,就一直支持并发的概念,例如线程和锁等。并发编程是现代软件工程中不可或缺的一部分,尤其是在多核处理器普及的今天,利用好并发可以极大地提升程序...

    java并发编程艺术

    锁机制是Java并发编程中的另一大主题,包括内置锁(互斥锁)和显式锁(如`ReentrantLock`)。内置锁是`synchronized`关键字提供的,而显式锁提供了更细粒度的控制和更丰富的功能。书中可能还会讨论读写锁(`...

    java并发编程

    Java并发编程是Java开发者必须掌握的关键技能之一,它涉及到如何在多线程环境中高效、安全地执行程序。并发编程能够充分利用多核处理器的计算能力,提高应用程序的响应速度和整体性能。《Java编程并发实战》这本书是...

    Java 并发编程实战.pdf

    根据提供的信息,“Java 并发编程实战.pdf”这本书聚焦于Java并发编程的实践与应用,旨在帮助读者深入了解并掌握...无论是对于初学者还是有一定经验的开发者来说,《Java并发编程实战》都是一本值得深入学习的好书。

    JAVA并发编程艺术pdf版

    《JAVA并发编程艺术》是Java开发者深入理解和掌握并发编程的一本重要著作,它涵盖了Java并发领域的核心概念和技术。这本书详细阐述了如何在多线程环境下有效地编写高效、可靠的代码,对于提升Java程序员的技能水平...

    java并发编程实践pdf笔记

    这本书的读书笔记涵盖了多个关键知识点,旨在帮助读者深入理解Java并发编程的核心概念。 1. **线程和进程的区别** - **线程** 是程序执行的最小单位,一个进程中可以有多个线程同时执行,共享同一块内存空间,通信...

    Java并发编程实践高清pdf及源码

    4. **线程池**:`ExecutorService`是Java并发框架的核心,它管理一组可重用线程,有效地调度和执行任务。`ThreadPoolExecutor`是其最常见的实现,允许自定义线程池参数。 5. **并发工具类**:如`CountDownLatch`、`...

    java并发编程书籍

    2. **同步机制**:Java并发编程的核心在于同步,以防止数据不一致性和资源竞争。`synchronized`关键字用于实现临界区的互斥访问,确保同一时刻只有一个线程执行特定代码块。此外,还有`wait()`, `notify()`, `...

    java并发编程内部分享PPT

    这份“java并发编程内部分享PPT”显然是一个深入探讨这一主题的资料,旨在帮助开发者理解并掌握Java并发编程的核心概念和技术。 在Java并发编程中,首先我们需要了解的基本概念是线程。线程是操作系统分配CPU时间的...

    Java并发编程实战华章专业开发者书库 (Tim Peierls 等 美Brian Goetz).pdf

    《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南,由Tim Peierls等人与Brian Goetz合著,旨在帮助Java开发者理解和掌握在多线程环境中编写高效、安全的代码。这本书由拥有丰富经验的JDK并发大师及...

    java并发编程实战(英文版)

    综上所述,《Java并发编程实战》不仅涵盖了Java并发编程的基础知识和技术细节,还包含了丰富的实践经验和前瞻性的思考,是任何一位从事Java开发工作的程序员不可或缺的学习资源。无论是初学者还是有经验的开发者都能...

    java 并发编程的艺术pdf清晰完整版 源码

    《Java并发编程的艺术》这本书是Java开发者深入理解并发编程的重要参考书籍。这本书全面地介绍了Java平台上的并发和多线程编程技术,旨在帮助开发者解决在实际工作中遇到的并发问题,提高程序的性能和可伸缩性。 ...

Global site tag (gtag.js) - Google Analytics