`
tree_161219
  • 浏览: 85964 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

转:java并发编程实践笔记

阅读更多
出处 : http://galaxystar.iteye.com/blog/168950

1, 保证线程安全的三种方法 :
    a, 不要跨线程访问共享变量
    b, 使共享变量是 final类型的
    c, 将共享变量的操作加上同步

2, 一开始就将类设计成线程安全的 , 比在后期重新修复它 ,更容易 .

3, 编写多线程程序 , 首先保证它是正确的 , 其次再考虑性能 .

4, 无状态或只读对象永远是线程安全的 .

5, 不要将一个共享变量裸露在多线程环境下 (无同步或不可变性保护 )

6, 多线程环境下的延迟加载需要同步的保护 , 因为延迟加载会造成对象重复实例化

7, 对于 volatile 声明的数值类型变量进行运算 , 往往是不安全的 (volatile 只能保证可见性 , 不能保证原子性 ).
详见 volatile 原理与技巧中 , 脏数据问题讨论 .

8, 当一个线程请求获得它自己占有的锁时 ( 同一把锁的嵌套使用 ), 我们称该锁为可重入锁 .
在 jdk1.5 并发包中 , 提供了可重入锁的 java 实现 -ReentrantLock.

9, 每个共享变量 , 都应该由一个唯一确定的锁保护 .
创建与变量相同数目的 ReentrantLock, 使他们负责每个变量的线程安全 .

10,虽然缩小同步块的范围 , 可以提升系统性能 .
但在保证原子性的情况下 , 不可将原子操作分解成多个 synchronized块 .

11, 在没有同步的情况下 , 编译器与处理器运行时的指令执行顺序可能完全出乎意料 .
原因是 , 编译器或处理器为了优化自身执行效率 , 而对指令进行了的重排序 (reordering).

12, 当一个线程在没有同步的情况下读取变量 , 它可能会得到一个过期值 , 但是至少它可以看到那个
线程在当时设定的一个真实数值 . 而不是凭空而来的值 . 这种安全保证 , 称之为最低限的安全性 (out-of-thin-air safety)

在开发并发应用程序时 , 有时为了大幅度提高系统的吞吐量与性能 , 会采用这种无保障的做法 .
但是针对 , 数值的运算 , 仍旧是被否决的 .

13, volatile 变量 , 只能保证可见性 , 无法保证原子性 .
详见 volatile原理与技巧

14, 某些耗时较长的网络操作或 IO, 确保执行时 , 不要占有锁 .

15, 发布 (publish) 对象 , 指的是使它能够被当前范围之外的代码所使用 .( 引用传递 )
对象逸出 (escape), 指的是一个对象在尚未准备好时将它发布 .

原则 : 为防止逸出 , 对象必须要被完全构造完后 , 才可以被发布 ( 最好的解决方式是采用同步 )

this 关键字引用对象逸出
例子 : 在构造函数中 , 开启线程 , 并将自身对象 this 传入线程 , 造成引用传递 .
而此时 , 构造函数尚未执行完 , 就会发生对象逸出了 .

16, 必要时 , 使用 ThreadLocal变量确保线程封闭性 (封闭线程往往是比较安全的 , 但一定程度上会造成性能损耗 )
封闭对象的例子在实际使用过程中 , 比较常见 , 例如 hibernate openSessionInView机制 , jdbc的 connection机制 .

17, 单一不可变对象往往是线程安全的 (复杂不可变对象需要保证其内部成员变量也是不可变的 )
良好的多线程编程习惯是 : 将所有的域都声明为 final, 除非它们是可变的

18, 保证共享变量的发布是安全的
    a, 通过静态初始化器初始化对象 (jls 12.4.2 叙述 , jvm 会保证静态初始化变量是同步的 )
    b, 将对象申明为 volatile 或使用 AtomicReference
    c, 保证对象是不可变的
    d, 将引用或可变操作都由锁来保护

19, 设计线程安全的类 , 应该包括的基本要素 :
    a, 确定哪些是可变共享变量
    b, 确定哪些是不可变的变量
    c, 指定一个管理并发访问对象状态的策略

20, 将数据封装在对象内部 , 并保证对数据的访问是原子的 .
建议采用 volatile javabean 模型或者构造同步的 getter,setter.

21, 线程限制性使构造线程安全的类变得更容易 , 因为类的状态被限制后 , 分析它的线程安全性时 , 就不必检查完整的程序 .

22, 编写并发程序 , 需要更全的注释 , 更完整的文档说明 .

23, 在需要细分锁的分配时 , 使用 java监视器模式好于使用自身对象的监视器锁 .
前者的灵活性更好 .

Object target = new Object();
// 这里使用外部对象来作为监视器 , 而非 this
synchronized(target) {
    // TODO
}

针对 java monitor pattern, 实际上 ReentrantLock的实现更易于并发编程 .
功能上 , 也更强大 .

24, 设计并发程序时 , 在保证伸缩性与性能折中的前提下 , 优先考虑将共享变量委托给线程安全的类 .
由它来控制全局的并发访问 .

25, 使用普通同步容器 (Vector, Hashtable) 的迭代器 , 需要外部锁来保证其原子性 .
原因是 , 普通同步容器产生的迭代器是非线程安全的 .

26, 在并发编程中 , 需要容器支持的时候 , 优先考虑使用 jdk 并发容器
(ConcurrentHashMap, ConcurrentLinkedQueue, CopyOnWriteArrayList...).

27, ConcurrentHashMap, CopyOnWriteArrayList
并发容器的迭代器 , 以及全范围的 size(), isEmpty() 都表现出弱一致性 .
他们只能标示容器当时的一个数据状态 . 无法完整响应容器之后的变化和修改 .

28, 使用有界队列 , 在队列充满或为空时 , 阻塞所有的读与写操作 . ( 实现生产 - 消费的良好方案 )
BlockQueue 下的实现有 LinkedBlockingQueue 与 ArrayBlockingQueue, 前者为链表 , 可变操作频繁优先考虑 , 后者为数组 , 读取操作频繁优先考虑 .
PriorityBlockingQueue 是一个按优先级顺序排列的阻塞队列 , 它可以对所有置入的元素进行排序 ( 实现 Comparator 接口 )

29, 当一个方法 , 能抛出 InterruptedException, 则意味着 , 这个方法是一个可阻塞的方法 , 如果它被中断 , 将提前结束阻塞状态 .
当你调用一个阻塞方法 , 也就意味着 , 本身也称为了一个阻塞方法 , 因为你必须等待阻塞方法返回 .

如果阻塞方法抛出了中断异常 , 我们需要做的是 , 将其往上层抛 , 除非当前已经是需要捕获异常的层次 .
如果当前方法 , 不能抛出 InterruptedException, 可以使用 Thread.currentThread.interrupt() 方法 , 手动进行中断 .
分享到:
评论

相关推荐

    java并发编程实践笔记

    java并发编程实践笔记java并发编程实践笔记java并发编程实践笔记java并发编程实践笔记

    java并发编程实践笔记资料.pdf

    java并发编程实践笔记资料.pdf

    java并发编程实践pdf笔记

    java并发编程实战pdf学习笔记 总结了重要的知识点

    [原]Java并发编程实践-读书笔记

    《Java并发编程实践》一书的个人读书笔记。主要列举包括各个章节的关键知识点,便于反复阅读和知识复习掌握。

    java并发编程实践

    Java是最先支持多线程的开发的语言之一,Java从一开始就支持了多线程能力,因此Java开发者能常遇到上面描述的...这也是我想为Java并发技术而写这篇系列的原因。作为对自己的笔记,和对其他Java开发的追随者都可获益的。

    JAVA并发编程实践-线程池-学习笔记

    当调用 start 启动线程时 Java 虚拟机会调 用该类的 run方法。 那么该类的 run() 方法中就是调用了 Runnable 对象的 run() 方法。 我 们可以继承重写Thread 类,在其 start 方法中添加不断循环调用传递过来的 ...

    JAVA并发编程实践-线程执行-学习笔记

    的管理,这种分离还在不同事务间划分了自然的分界线,在程序出现错误时可以很方便地进行恢复,还有利于提高程序的并发性。围绕任务执行来管理应用程序时,第一步要指明一个清晰的任务边界,理想情况下,任务是 独立...

    JAVA并发编程实践-线程安全-学习笔记

    线程安全就是对共享的、可变的状态进行管理,对象的状态就是它的数据,换句话说就是在不可控制的并发访问中保护数据。

    JAVA并发编程实践-线程对象与组合对象-学习笔记

    使用java.util.concurrent类库构造安全的并发应用程序的基础。共享其实就是某一线程的数据改变对其它线程可见,否则就会出现脏数据。

    JAVA并发编程实践-构建执行程序块-学习笔记

    在实践中,委托是创建线程安全类最有效的策略之一:用已有的线程安全类来管理所 有状态即可。

    JAVA并发编程实践-线程的关闭与取消-学习笔记

    java中没有提供任何机制,来安全是强迫线程停止手头的工作,Thread.stop和 Thread.suspend方法存在严重的缺陷,不能使用。程序不应该立即停止,应该采用中断这种协作机制来处理,正确的做法是:先清除当前进程中的...

    Java 并发学习笔记:进程和线程,并发理论,并发关键字,Lock 体系,原子操作类,发容器 & 并发工具,线程池,并发实践

    Java 并发学习笔记: 进程和线程, 并发理论, 并发关键字, Lock 体系, 原子操作类, 发容器 & 并发工具, 线程池, 并发实践 Java是一种面向对象的编程语言,由Sun Microsystems于1995年推出。它是一种跨平台的...

    learn-thread:Java多线程学习笔记

    学习线程介绍Java多线程学习PDF格式Java并发编程的艺术.pdf JAVA并发编程实践.pdf图解Java多线程设计模式-第2版.pdf代码code1是《 Java并发编程的艺术》的源码ThreadDesignPatterns是《图解Java多线程设计模式》第1...

    Java面试题和学习笔记

    Linux面试专题及答案+ActiveMQ消息中间件面试专题+Java基础面试题+MySQL性能优化的21个最佳实践+微服务面试专题及答案+深入理解java虚拟机+设计模式面试专题及答案+开源框架面试专题及答案+并发编程及答案+Spring...

    Java 并发编程学习笔记之核心理论基础

    Java语言从第一版本开始内置了对多线程的支持,这一点在当年是非常了不起的,但是当我们对并发编程有了更深刻的认识和更多的实践后,实现并发编程就有了更多的方案和更好的选择。本文是对并发编程的核心理论做了下小...

    Java 学习笔记极其详细版(包括一些个人色彩不仅仅是纯笔记)

    本Jva(Java)学习笔记是一份深入且详尽的教程,不仅包括Java的基础知识,还融入了作者的个人见解和实际编程经验。内容涵盖: Java基础:数据类型、控制流、异常处理。 面向对象编程:类与对象、继承、多态、封装。...

    Java工程师面试题-并发编程-高级架构

    Java并发编程.pdf JAVA核心知识点整理.pdf Java高级架构知识点整理.pdf Java高级架构面试知识点整理.pdf JVM与性能优化知识点整理.pdf MySQL性能调优与架构设计解析文档.pdf Nginx入门到实战.pdf springCloud笔记....

    2023最新Java面试题面试经验笔记项目

    2022java面试题、JVM面试题、多线程面试题、并发编程、Redis面试题、MySQL面试题、Java2022面试题、Netty面试题 一、内容概览 本次分享的资源涵盖了Java面试的各个方面,从基础知识到高级技术,从数据库到框架应用...

    高级java笔试题-Java-Note:一个Java程序员的笔记本

    并发编程实战 自己动手写Java虚拟机,张秀宏 Spring 技术内幕:深入解析 Spring架构与设计原理(第2版) 数据库 MySQL技术内幕:Innodb 存储引擎第二版,姜承尧 Redis 设计与实现 操作系统: Linux 私

Global site tag (gtag.js) - Google Analytics