Java并发编程实战读书笔记一

第1章 简介

第2章 线程安全性

1个状态变量线程安全的模式

 多个状态变量线程不安全的模式,在A线程lastNumbers.set和lastFactors.set之间B线程进行这两个set就出问题了,

AtomicReference是替代对象引用的线程安全类

使用synchronized性能很差

 synchronized是可重入锁,下面实例先获得LoggingWidget的对象锁(对象锁=方法锁),然后调用doSomething方法,那么当前线程当前对象锁的计数器+1,由于锁是可重入的,那么可以继续调用super.doSomething,计数器再+1,两次doSomething的调用需要同一个对象锁

 优化性能方式:减小锁粒度,只在需要修改共享变量的地方加锁

 第3章 对象的共享

3.1可见性

经本地测试可能输出0、42、或者死循环。因为无法保证主线程写入的ready值和number值对于读线程来说是可见的。而且ready和number的赋值可能会被指令重排,不一定是程序见到的顺序

 如下图,如果某个线程调用了set,那么另外一个正在调用get的线程可能会看到更新后的value值,也可能看不到

 如下需要对set和get都进行同步

 3.1.2 非原子的64位操作

即使不考虑失效数据问题,在多线程程序中使用共享且可变的 long 和 double 等类型的变量也是不安全的,除非用关键字volatile 来声明它们,或者用锁保护起来。

3.1.3加锁与可见性

加锁的行为不仅仅局限于互斥行为,还包括内存可见性。为了确保所有线程都能看到共享变量的最新值,所有执行读操作或者写操作的线程都必须在同一个锁上同步

3.1.4Volatile变量

访问 volatile 变量时不会执行加锁操作,因此也就不会使执行阻塞,因此 volatile 变量是一种比 sychronized 关键字更轻量级的同步机制

volatile用法
当且仅当满足以下所有条件时,才应该使用 volatile 变量:
1.对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值
2.该变量不会与其他状态变量一起纳入不变性条件中
3.在访问变量时不需要加锁

 3.2发布与逸出

3.3线程封闭

线程封闭常见应用jdbc

 3.3.3ThreadLocal
保存了特定于线程的值

 3.4.2 示例:使用Volatile类型 来发布不可变对象

final类型成员变量在构造方法中初始化,不能在方法中改变指向

 volatile用于对象

3.5安全发布 

第四章 对象的组合

4.1设计线程安全的类

4.3.2 独立的状态变量

CopyOnWriteArrayList 线程安全的集合

如下,线程不安全样例,list和synchronized不是同一把锁,方法执行时,另一个线程可以同时修改list

4.4.1 客户端加锁机制

 改为如下同一把锁

猜你喜欢

转载自blog.csdn.net/qq_35572013/article/details/127922893
今日推荐