Java多线程——不变性与安全发布

1、不变性

  某个对象在被创建后其状态就不能被修改,那么这个对象就称为不可变对象,不可变对象一定是线程安全的。不可变对象很简单。他们只有一种状态,并且该状态由构造函数来控制。

  当满足以下条件时,对象才是不可变的:(1)、对象创建以后其状态就不能改变;(2)、对象的所有域都是final类型;(3)、对象是正确创造的(在对象创建期间,this引用没有溢出)。

1.1 final域

  关键字final用于构造不可变对象,final类型的域是不能修改的(但是final域所引用的对象是可变的,那么这些引用的对象是可以修改的),即使对象是可变的,通过将可变对象的某些域声明为final类型,相当于告诉维护人员这些域是不可变化的。

 

2、正确发布一个对象

  正确发布一个对象遇到的两个问题:(1)引用本身要被其他线程看到;(2)对象的状态要被其他线程看到。

  在多线程编程中,首要的原则,就是要避免对象的共享,因为如果没有对象的共享,那么多线程编写要轻松得多,但是,如果要共享对象,那么除了能够正确的将构造函数书写正确外,如何正确的发布也是一个很重要的问题。

  我们看下面的代码:

 1 public class Client {
 2     public Holder holder;
 3     
 4     public void initialize(){
 5         holder = new Holder(42);
 6     }
 7 }
 8 
 9 
10 public class Holder {
11     int n;
12     public Holder(int n) {
13         this.n = n;
14     }
15     public void assertSanity() {
16         if(n != n)
17              throw new AssertionError("This statement is false.");
18     }
19 }
View Code

  在Client类中,Holder对象被发布了,但是这是一个不正确的发布。由于可见性问题,其他线程看到的Holder对象将处于不一致的状态,即使在该对象的构成构函数中已经正确的该构建了不变性条件,这种不正确的发布导致其他线程看到尚未创建完成的对象。主要是Holder对象的创建不是原子性的,可能还未构造完成,其他线程就开始调用Holder对象。

由于没有使用同步的方法来却确保Holder对象(包含引用和对象状态都没有)对其他线程可见,因此将Holder成为未正确发布。问题不在于Holder本身,而是其没有正确的发布。上面没有正确发布的可能导致的问题:

  • 别的线程对于holder字段,可能会看到过时的值,这样就会导致空引用,或者是过时的值(即使holder已经被设置了)(引用本身没有被别的线程看到)
  • 更可怕的是,对于已经更新holder,及时能够看到引用的更新,但是对于对象的状态,看到的却可能是旧值,对于上面的代码,可能会抛出AssertionError异常

主要是holder = new Holder(42);这个代码不是原子性的,可能在构造未完成时,其他线程就会调用holder对象引用,从而导致不可预测的结果。

2.1安全发布常用模式

  要安全的发布一个对象,对象的引用和对象的状态必须同时对其他线程可见。一般一个正确构造的对象(构造函数不发生this逃逸),可以通过如下方式来正确发布:

  (1)、在静态初始化函数中初始化一个对象引用

  (2)、将一个对象引用保存在volatile类型的域或者是AtomicReference对象中

  (3)、将对象的引用保存到某个正确构造对象的final类型的域中。

  (4)、将对象的引用保存到一个由锁保护的域。

  

  在线程安全容器内部同步意味着,在将对象放到某个容器中,比如Vector中,将满足上面的最后一条需求。如果线程A将对象X放到一个线程安全的容器中,随后线程B读取这个对象,那么可以确保可以确保B看到A设置的X状态,即便是这段读/写X的应用程序代码没有包含显示的同步。下面容器内提供了安全发布的保证:

  (1)、通过将一个键或者值放入Hashtable、synchronizedMap或者ConcurrentMap中,可以安全将它发布给任何从这些容器中访问它的线程。

  (2)、通过将某个元素放到Vector、CopyOnWriteArrayList、CopyOnWriteArraySet、synchroizedList,可以将该元素安全的发布到任何从这些容器中访问该元素的线程。

  (3)、通过将元素放到BlockingQueue或者是ConcrrentLinkedQueue中,可以将该元素安全的发布到任何从这些访问队列中访问该元素的线程。

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

  静态初始化器由JVM在类的初始化阶段执行,由于JVM内部存在同步机制,所以这种方式初始化对象都可以被安全的发布。对于可变对象,安全的发布之时确保在发布当时状态的可见性,而在随后的每次对象的访问时,同样需要使用同步来确保修改操作的可见性。

  

转载于:https://www.cnblogs.com/Hxinguan/p/7471461.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/371332.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中tr不能显示字符_垃圾文本识别中基本操作指南和错误总结,第三部分

创建模型需要用到机器学习的库,所以我们先下载sklearn库sklearn库下载完成后再输入库文件,就可以完美运行。然后就是划分测试集和训练集,需要注意的是,在从数据处理函数中导入数据时,足足运行了有将近30多秒&#xff0…

mvc后台post发送json数据

代码比较简单&#xff0c;不废话&#xff0c;直接上代码&#xff1a; /// <summary>/// 提交json数据&#xff0c;并接收/// </summary>/// <param name"apipath">要请求的服务器地址</param>/// <param name"jsonStr">要提…

(转载)20分钟读懂程序集

转自&#xff1a;http://www.cnblogs.com/damonlan/p/3221347.html 说到程序集&#xff0c;我刚开始对这个名词特别的郁闷&#xff01;~。然后 前些天花了些时间 好好读了一下&#xff0c;现在比较清晰了&#xff0c;把一些书上看到的 记下来&#xff0c;以飨读者。希望没浪费你…

大数据胸_喂母乳会导致胸下垂?!你被这个谣言骗了多少年?

很多人认为&#xff0c;给宝宝喂奶会导致胸下垂。有些爱美的妈妈&#xff0c;甚至在宝宝出生6个月后就着急断奶。那么&#xff0c;喂奶真的会导致胸下垂么&#xff1f;给大家讲两个真实的调查结果哈~2004年的一次针对496名新妈妈的调查结果显示&#xff0c;有75%的母乳喂养母亲…

Spring Shell项目发布

Spring Source昨天发布了Spring Shell 。 Spring Shell是一个交互式Shell&#xff0c;可以使用基于Spring的编程模型轻松地通过命令进行扩展。 它是通过除去OSGi依赖项从Spring Roo项目中提取的&#xff0c;并变成了一个独立项目。 这使得那些只希望使用交互式外壳功能的人更容…

自制ACL+DHCP实验(初版)

&#xff08;实验用gns模拟器&#xff09; ACL 实验拓扑&#xff1a; 实验要求&#xff1a; 1.1.1.1→3.3.3.3 不通 11.11.11.11→3.3.3.3 通 2.2.2.2→3.3.3.3 通 实验步骤&#xff1a; 步骤一&#xff1a;基本配置 R1&#xff1a; R1#conf t R1(config)#int lo0 R1(config-if…

pil 图像最大值_第97天:图像库 PIL(二)

上节我们讲了 Python 的图像处理库 PIL 的基本图像处理功能&#xff0c;打开了 PIL 的神秘面纱。这节我们接着讲 PIL 的 Image 模块的常用方法。Image 模块的方法convertImage.convert(modeNone, matrixNone, ditherNone, palette0, colors256)参数说明&#xff1a;mode&#x…

c#的委托用法delegate

转载于:https://www.cnblogs.com/douzujun/p/6555886.html

yii2.0

yii是一个高性能的适用于开发web2.0应用的框架&#xff0c;它自带丰富的功能&#xff0c;包括mvc&#xff0c;dao/aciverecord&#xff0c;缓存&#xff0c;身份验证和基于角色的访问控制&#xff0c;脚手架&#xff0c;测试等&#xff0c;可显著缩短开发时间yii只加载你需要的…

Java中常见的代码冲突

在工作中&#xff0c;最近我对现有Java项目进行了代码清理。 完成该练习后&#xff0c;我可以看到在代码中一次又一次地发生了一组常见的代码冲突。 因此&#xff0c;我想出了此类常见违规的清单&#xff0c;并与同行分享&#xff0c;以使人们有意识地提高代码质量和可维护性。…

np读取csv文件_被 Pandas read_csv 坑了

-- 不怕前路坎坷&#xff0c;只怕从一开始就走错了方向Pandas 是python的一个数据分析包&#xff0c;纳入了大量库和一些标准的数据模型&#xff0c;提供了高效地操作大型数据集所需的工具。Pandas 就是为解决数据分析任务生的&#xff0c;无论是数据分析还是机器学习项目数据预…

Python 第三方库 cp27、cp35 等文件名的含义

What does version name ‘cp27’ or ‘cp35’ mean in Python? 如对于 gensim-0.12.4-cp27-none-win_amd64.whl文件名而言&#xff0c;将其文件名拆分的话&#xff0c;含义分别是&#xff1a; 0.12.4 - package version, they may be using semantic versioningcp27 - this p…

JAVA: 序列化

对象序列化 - 一个对象可以被表示为一个字节序列&#xff0c;保存对象的类型信息、对象的数据&#xff0c;还有对象中的数据类型&#xff0c;以便存储或传输。 反序列化 - 将序列化对象写入文件之后&#xff0c;可以从文件中读取出来&#xff0c;并且对它进行反序列化&#xff…

寻找随机的错误-一个真实的故事

几周前&#xff0c;我完成了RapidFTR开源项目的错误查找 &#xff0c;这花了我三个晚上。 我认为可能值得分享狩猎的故事。 本文将介绍我的工作。 我将概述我的旅程&#xff0c;以实际找到正在发生的事情的根本原因。 我在本文中的目标是突出显示可以使用的技术示例&#xff0c…

铃木uy125摩托车机油_UY125 新瑞梦UM125发布 济南铃木于湖南株洲吹响国IV集结号...

​4月18日&#xff0c;济南铃木在湖南株洲天台开元酒店举行了2019年新品发布会&#xff0c;并于现场发布了两款极具终端战略意义的新款国IV车型&#xff0c;分别为定位“实用运动”的全新个性化踏板车型UY125&#xff0c;以及能够进一步巩固济南铃木在国IV入门级踏板车型领域绝…

473. 核电站问题

★ 输入文件&#xff1a;nucle.in 输出文件&#xff1a;nucle.out 简单对比 时间限制&#xff1a;1 s 内存限制&#xff1a;128 MB 【问题描述】 一个核电站有 N 个放核物质的坑&#xff0c;坑排列在一条直线上。如果连续 M 个坑中放入核物质&#xff0c;则会发生爆炸&…

js判断时间是早上还是下午_牛奶早上喝好,还是晚上喝好?没想到“最佳时间”是这个点,颠覆了!...

都说喝牛奶好&#xff0c;要多喝。可什么时间喝牛奶最好呢&#xff1f;是饭前、饭后还是睡前&#xff1f;又或者喝酒前&#xff1f;确实得好好说说。传言&#xff1a;空腹时身体比较缺能量&#xff0c;牛奶里的蛋白会去提供能量&#xff0c;不会去构成和修复组织(比如修复皮肤)…

Java模因拒绝死亡

也有标题&#xff1b; 我的宠物讨厌Java编码。 有许多Java模因让我很烦&#xff0c;部分是因为它们总是一个坏主意&#xff0c;但主要是因为人们在找到更好的替代方案后的几年里仍在继续使用它们。 使用StringBuffer代替StringBuilder 从2004年开始&#xff0c;用于StringBuf…

Python TK编程第一部分 Hello Again

当你想写大一点的程序的时候&#xff0c;将你的代码封装到一个或者多个类里会是一个不错的办法。下面hello world这个例子来自Matt Conway的Tkinter Life Preserver. [python]view plain copy from Tkinter import * class App: def __init__(self, master): …

视网膜脱离oct报告图_刚刚,爱尔眼科发布关于艾芬医生诊疗过程的核查报告

刚刚&#xff0c;爱尔眼科医院集团发布关于艾芬女士诊疗过程的核查报告&#xff0c;内容如下&#xff1a;得悉艾芬女士对武汉爱尔眼科医院白内障诊疗存疑&#xff0c;爱尔眼科医院集团高度重视&#xff0c;第一时间成立了工作组奔赴武汉&#xff0c;对事件的诊疗全过程开展了核…