(十二)volatile变量
volatile变量 ,用来确保将变量的更新操作通知到其他线程。当把变量申明为volatile类型后,编译器与运行时都会注意到这个变量是共享的。因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型时总会返回最新写入的值。
仅当volatile变量能简化代码的实现以及对同步策略的验证时,才应该使用它们。如果在验证正确性时需要对可见性进行复杂的判断,那么就不要使用volatile变量。volatile变量的正确使用方式包括:确保它们自身状态的可见性,确保它们所引用对象的状态的可见性,以及标识一些重要的程序生命周期事件的发生(例如,初始化或关闭)。
一个典型用法:
检查某个状态标记以判断是否退出循环。示例中,线程试图通过类似于数绵羊的传统方法进入休眠状态,asleep必须为volatile变量,否则,当asleep被另一个线程修改时,执行判断的线程却发现不了。
volatile boolean asleep;
……
while(!asleep)
countSomeSheep();

volatile变量通常用做某个操作完成,发生中断或者状态的标志。volatile的语义不足以确保递增操作(count++)的原子性,除非你能确保只有一个线程对变量执行写操作。
加锁机制既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性。

(十三) ThreadLocal :
http://www.cnblogs.com/dolphin0520/p/3920407.html
http://www.iteye.com/topic/103804
首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。

另外,说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本。通过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,ThreadLocal实例是作为map的key来使用的。

如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。

ThreadLocal是如何为每个线程创建变量的副本的:
  首先,在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。
  初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。
  然后在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLocals里面查找。

ThreadLocal的应用:

private static final ThreadLocal threadSession = new ThreadLocal();public static Session getSession() throws InfrastructureException {Session s = (Session) threadSession.get();try {if (s == null) {s = getSessionFactory().openSession();threadSession.set(s);}} catch (HibernateException ex) {throw new InfrastructureException(ex);}return s;
}

(十四) 不可变对象
如果某个对象在被创建后其状态就不能被修改,那么这个对象就称为不可变对象。不可变对象一定是线程安全的。
不可变性的所有需求:状态不可修改,所有域都是final类型,以及正确的构造过程。

任何线程都可以在不需要额外同步的情况下安全的访问不可变对象,即使在发布这些对象时没有使用同步。

(十五)final类型的域
在没有额外同步的情况下,也可以安全的访问final类型的域,然而如果final类型的域所指向的是可变对象,那么在访问这些域所指向的对象的状态时仍然需要同步。

(十六)如何安全发布一个对象
要安全发布一个对象,对象的引用以及对象的状态必须同时对其他线程可见。一个正确构造的对象可以通过以下方式来发布:
1.在静态初始化函数中初始化一个对象引用
2.将对象的引用保存到volatile类型的域或者AtomicReferance对象中。
3.将对象的引用保存到某个正确构造对象的final类型域中。
4.将对象的引用保存到一个由锁保护的域中 : 如将对象放入到某个容器,vector或synchronizedList。

线程安全库中的容器:Hashtable,synchronizedMap , ConcurrentMap
vector synchronizedList synchronizedSet CopyOnWriteList CopyOnWriteArraySet
BlockingQueue ConcurrentLinkedQueue
类库中的其他数据传递机制(如Future和Exchanger)同样能实现安全发布。

通常,发布一个静态构造的对象,最简单和最安全的方式是使用静态的初始化器:
public static Holder holder = new Holder(42)

(十七)事实不可变对象
如果对象在技术上来看是可变的,但其状态在发布后不会再改变,那么把这种对象称为“事实不可变对象(Effectively Immutable Object)”.
好处:不仅可以简化开发过程,而且还能由于减少了同步而提高性能。

在没有额外的同步情况下,任何线程都可以安全地使用被安全发布的事实不可变对象。
例如,Date本身是可变的,假设需要维护一个Map对象,其中保存了每位用户的最近登录时间:
public Map

《java并发编程实战》笔记(第3章)相关推荐

  1. Java并发编程实战笔记2:对象的组合

    设计线程安全的类 在设计现车让安全类的过程之中,需要包含以下三步: 找出构成对象状态的所有变量 找出约束状态变量的不变性条件 建立对象状态的并发访问策略 实例封闭 通过封闭机制与合适的加锁策略结合起来 ...

  2. Java并发编程实战笔记—— 并发编程1

    1.如何创建并运行java线程 创建一个线程可以继承java的Thread类,或者实现Runnabe接口. public class thread {static class MyThread1 ex ...

  3. Java并发编程实战笔记

    如果当多个线程访问同一个可变的状态变量时没有使用合适的同步,那么程序就会出现错误.有三种方式可以修复这个问题: i.不在线程之间共享该状态变量 ii.将状态变量修改为不可变的变量 iii.在访问状态变 ...

  4. 《java并发编程实战》第11章-性能与可伸缩性

    11.1 对性能的思考 11.1.1 性能的提升意味着什么 提升性能意味着用更少的资源做更多的事情, 在任何时刻,提升性能的前提是要保证程序的正确性 当操作由于某种特定的资源而受到限制时,通常就称该操 ...

  5. Java并发编程实战_不愧是领军人物!这种等级的“Java并发编程宝典”谁能撰写?...

    前言 大家都知道并发编程技术就是在同一个处理器上同时的去处理多个任务,充分的利用到处理器的每个核心,最大化的发挥处理器的峰值性能,这样就可以避免我们因为性能而产生的一些问题. 大厂的核心负载肯定是非常 ...

  6. 【极客时间】《Java并发编程实战》学习笔记

    目录: 开篇词 | 你为什么需要学习并发编程? 内容来源:开篇词 | 你为什么需要学习并发编程?-极客时间 例如,Java 里 synchronized.wait()/notify() 相关的知识很琐 ...

  7. 《Java 并发编程实战》--读书笔记

    Java 并发编程实战 注: 极客时间<Java 并发编程实战>–读书笔记 GitHub:https://github.com/ByrsH/Reading-notes/blob/maste ...

  8. Java并发编程实战————恢复中断

    中断是一种协作机制,一个线程不能强制其他线程停止正在执行的操作而去执行其他操作. 什么是中断状态? 线程类有一个描述自身是否被中断了的boolean类型的状态,可以通过调用 .isInterrupte ...

  9. Java并发编程实战————Executor框架与任务执行

    引言 本篇博客介绍通过"执行任务"的机制来设计应用程序时需要掌握的一些知识.所有的内容均提炼自<Java并发编程实战>中第六章的内容. 大多数并发应用程序都是围绕&qu ...

  10. 前置条件,不变性条件,后置条件 --《java并发编程实战》

    阅读<java并发编程实战>4.1.1章 收集同步需求时, 反复出现了"不变性条件","不可变条件","后验条件",令我一头雾水 ...

最新文章

  1. 从 SGD 到 Adam —— 深度学习优化算法概览 各种优化器 重点
  2. (1)学习数组,集合,IEnumerable接口,引申学习迭代器
  3. 解决:Sublime Text3 packagecontrol.io 无法访问的问题
  4. LOJ P1155 双栈排序 二分图染色 图论
  5. 自定义分页模板(银角大王版)
  6. 前端攻城狮学习笔记七:常见前端面试题之HTML/CSS部分(二)
  7. [C# 基础知识系列]专题六:泛型基础篇——为什么引入泛型
  8. 【图像处理】——特征匹配(SIFT特征检测器+FLANN特征匹配方法+KNN近邻最优匹配筛选)——cv.xfeatures2d.SIFT_create()sift.detectAndCompute
  9. 机器学习之线性回归的改进-岭回归
  10. JavaSE知识点:finalize,treeMap
  11. Javascript模块化编程 (附WebTrends的dcsMultiTrack方法浅述)
  12. cad道路里程桩号标注_CAD道路桩号自动编号插件
  13. 微信小程序的简单使用(做一个阻抗计算器)
  14. 自抗扰控制中的扩张状态观测器收敛性分析3
  15. linux 禁用超线程,Linux动态启用/禁用超线程技术
  16. java8 stream 原理_【修炼内功】[Java8] Stream是怎么工作的
  17. PCL 基于对应点分类的对象识别
  18. html 实现excel表格分页打印,excel分页-用了这么多年Excel才知道,按下这个键,一张纸便可打印全部内容...
  19. 浅谈微分求导+泰勒展开+生成函数
  20. 一段简单的C/C++病毒源程序

热门文章

  1. flask----后续
  2. MySql从入门到中级到事务
  3. 36.有效的数独,超简单做法,一看就懂
  4. 电热玻璃水壶CE认证检测标准介绍
  5. tp路由服务器无响应,路由器无法PPPOE链接上网老显示服务器无响应
  6. 笔记本硬盘坏了还能恢复数据吗 笔记本硬盘坏了怎么修复
  7. uniapp获取手机可接收的所有的WiFi名称与信号强度
  8. Cisco PacketTracer5---三层交换机连接路由器配置
  9. 看《大话西游》,你哭了么
  10. Java学习Day16(更新)--API