《Java并发编程实战》第3章-对象的共享

2 篇文章 0 订阅
1 篇文章 0 订阅
0.概念理解

对象状态:就是对象当中的各个成员变量;
对象发布:就是将对象的引用交给别人;
安全发布:创建对象需要一段时间,等彻底创建完了才把引用给别人(其他线程);
逸出/逃逸:不应该发布的对象被发布了;
不正确构造:this在构造过程中逸出(即使在构造函数最后一行也不行);
线程封闭:不要让不安全的对象被多线程共享;
不可变对象:只有一种状态的对象;
事实不可变对象:状态在发布后不会改变的可变对象;

1.为甚么存在对象共享的问题?

多个线程之间需要通信,需要操作同一组数据,以达到多线程协作的目的。

2.多线程之间共享对象时会存在什么样的问题?
  • 线程A在使用对象状态的同时线程B在修改对象状态,导致使用时读取到的对象状态是新老版本各一半,造成错误;
  • 一个线程在修改了对象状态后,其他线程不能够及时看到。
3.volatile的原理与应用
  • 原理:禁止指令重排,禁用寄存器等线程间不共享的缓存,不加锁不阻塞,成本只是略高;
  • 应用:作为状态标记以判断是否退出循环;
4.发布对象的几种情况
  • 将对象引用保存至公有静态变量;
  • 从非私有方法中返回一个引用;
  • 传递发布:发布对象的公有域都会被发布;
  • 发布一个内部类实例(隐含引用外部类this),不正确构造;
5.线程封闭的方式、应用场景与注意事项
  • 方式:
  • Ad-hoc(自己注意)、栈封闭(局部变量)、ThreadLocal(资源副本)
  • 应用场景:
  • Swing的可视化组件与数据模型的事件分发线程;
  • JDBC的Connection对象;
  • 注意:
  • 防止逸出:不要让外部传入的对象引用到栈内对象;
  • ThreadLocal仅仅用在分配操作开销高的对象上,否则用栈封闭即可;
  • ThreadLocal的滥用:将使用该机制的代码与框架代码耦合,在类之间引入隐含的耦合性,降低代码可重用性;
6.不可变对象不变性条件
  • 对象创建以后其状态就不能修改;
  • 对象的所有域都是final类型;
  • 对象是正确创建的(构造时this未逸出);
7.使用volatile+不可变对象保证线程安全的原理

不可变对象作为容器存放多个状态,要同步改动所有状态只有一种方式:重新new一个容器不可变对象,再把引用指过去,要及时可见则加volatile;

8.安全发布的几种办法
  • 在静态初始化函数中初始化一个对象引用;
  • 将对象引用保存在volatile或AtomicReference对象中;
  • 将对象引用保存到某个正确构造对象的final域中;
  • 将对象引用保存到一个由锁保护的域中;
9.保证线程安全地共享对象的几种方法
  • 线程封闭:修改操作封闭在单线程;
  • ThreadLocal
  • volatile+发布不可变对象
  • 安全发布事实不可变对象
其他需要注意的问题
  • 若无同步,编译器、处理器以及运行时都可能对操作执行顺序进行重排;
  • long与double写操作非原子,需要加volatile或锁;
  • 服务端程序调试启动JVM必须加-server;
  • 在构造函数中调用可改写方法可能使this逸出,可使用私有构造函数和公共工厂方法,确保初始化好了之后再发布;
  • Java内存模型中,final域能保证初始化过程安全性,也就是正确创建;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值