业务的可变性和不可变性分析_不可变性真的意味着线程安全吗?

业务的可变性和不可变性分析

我经常阅读有关“如果对象是不可变的,则它是线程安全的”的文章。 实际上,我从未找到过一篇使我相信不可变意味着线程安全的文章。 即使是Brian Goetz的Java Concurrency in Practice一书中关于不变性的一本书,也没有完全使我满意。 在这本书中,我们可以在一个框架中逐字阅读: 不可变对象始终是线程安全的 。 我认为这句话值得更多解释。

因此,我将尝试定义不变性及其与线程安全性的关系。

定义 不变性

我的定义是“不可变的对象是在构造后状态不会改变的对象”。 我故意含糊其词,因为没有人真正同意确切的定义。

线程安全

您可以在Internet上找到许多不同的“线程安全”定义。 定义它实际上非常棘手。 我会说线程安全代码是在多线程环境中具有预期行为的代码。 我让您定义“预期行为”…

字符串示例

让我们看一下String的代码(实际上只是一部分代码...):

public class String {private final char value[];/** Cache the hash code for the string */private int hash; // Default to 0public String(char[] value) {this.value = Arrays.copyOf(value, value.length);}public int hashCode() {int h = hash;if (h == 0 && value.length > 0) {char val[] = value;for (int i = 0; i < value.length; i++) {h = 31 * h + val[i];}hash = h;}return h;}
}

String被认为是不可变的。 看一下它的实现,我们可以推断出一件事:不可变的对象可以更改其内部状态(在本例中为延迟加​​载的哈希码),只要它在外部不可见即可。

现在,我将以一种非线程安全的方式重写hashcode方法:

public int hashCode() {if (hash == 0 && value.length > 0) {char val[] = value;for (int i = 0; i < value.length; i++) {hash = 31 * hash + val[i];}}return hash;}

如您所见,我删除了局部变量h并直接影响了变量hash 。 此实现不是线程安全的! 如果多个线程同时调用hashcode ,则每个线程的返回值可能不同。 问题是,这堂课是一成不变的吗? 由于两个不同的线程可以看到不同的哈希码,因此从外部角度来看,我们具有状态更改,因此它不是不可变的。

我们可以得出这样的结论: String是不可变的, 因为它是线程安全的,而不是相反的。 所以……说“做一些不可变的对象,它是线程安全的!”有什么意义? 但是请注意,您必须使不可变对象具有线程安全性!”

ImmutableSimpleDateFormat示例

在下面,我写了一个类似于SimpleDateFormat的类。

public class VerySimpleDateFormat {private final DateFormat formatter = SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT);public String format(Date d){return formatter.format(d);}
}

该代码不是线程安全的,因为SimpleDateFormat.format不是。

这个对象是不变的吗? 好问题! 我们已尽最大努力使所有字段均不可修改,我们不使用任何建议设置对象状态将改变的设置方法或方法。 实际上,内部SimpleDateFormat更改其状态,这就是它不安全线程的原因。 由于对象图中的某些内容发生了变化,因此即使它看起来像它,它也不是不变的。问题甚至不在于SimpleDateFormat更改其内部状态,而是在于它以一种非线程安全的方式进行操作。

总结这个例子,创建一个不可变的类并不容易。 最后一个关键字还不够,您必须确保对象的对象字段不会更改其状态,这有时是不可能的。

不可变的对象可以具有非线程安全的方法(没有魔术!)

让我们看一下下面的代码。

public class HelloAppender {private final String greeting;public HelloAppender(String name) {this.greeting = 'hello ' + name + '!\n';}public void appendTo(Appendable app) throws IOException {app.append(greeting);}
}

HelloAppender类绝对是不可变的。 方法appendTo接受Appendable 。 由于Appendable不能保证是线程安全的(例如StringBuilder ),因此附加到此Appendable会在多线程环境中引起问题。

结论

在某些情况下,创建不可变的对象绝对是一个好习惯,这对创建线程安全的代码有很大帮助。 但是当我在任何地方阅读时,我都感到困扰。 不可变对象是线程安全的 ,显示为公理。 我明白了这一点,但是我认为思考一下这总是很好,以便了解导致非线程安全代码的原因。

感谢Jose的评论,在本文的结尾我得出了不同的结论。 这都是关于不可变的定义。 需要澄清!

如果满足以下条件,则对象是不可变的:

  • 它的所有字段在使用之前都已初始化(这意味着您可以进行延迟初始化)
  • 字段的状态在初始化后不会更改(不更改表示对象图不会更改,即使子级的内部状态也是如此)

除非对象必须处理非线程安全的对象,否则不可变对象将始终是线程安全的。

参考: 不变性真的意味着线程安全吗? 从我们的JCG合作伙伴 Tibo Delor在InvalidCodeException博客中获得。


翻译自: https://www.javacodegeeks.com/2012/09/does-immutability-really-means-thread.html

业务的可变性和不可变性分析

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

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

相关文章

linux的system () 函数详解

system&#xff08;执行shell 命令&#xff09; 相关函数 fork&#xff0c;execve&#xff0c;waitpid&#xff0c;popen 表头文件 &#xff03;i nclude<stdlib.h> 定义函数 int system(const char * string); 函数说明 system()会调用…

隐马尔科夫模型C#语言算法实现

开发工具&#xff1a; Visual Studio v2010 .NET Framework 4 Client Profile 版本历史&#xff1a; V1.1 2011年06月09日 修正UMDHMM在Baum-Welch算法中存在的模型参数调整错误。 V1.0 2011年06月08日 将C语言实现的隐马尔科夫模型算法&#xff08;UMDHMM&#xff09;改为C#语…

绘制条形图python_小白学Python(13)——pyecharts 绘制 柱状图/条形图 Bar

Bar-基本示例 1 from example.commons importFaker2 from pyecharts importoptions as opts3 from pyecharts.charts importBar4 5 bar(6 Bar()7 .add_xaxis(Faker.choose())8 .add_yaxis("商家A", Faker.values())9 .add_yaxis("商家B", Faker.values())1…

初进JAVA职场面试小技巧:一个老学长的吐血之作!

看着一批批小白的遭遇&#xff0c;有些无奈&#xff0c;又跟我年轻时有些类似。今天正好有点时间&#xff0c;给你几个建议。 1、在结业之前一定要把自己参与过的项目仔细审视一下&#xff0c;一点要特别熟悉项目的流程功能&#xff0c;另外也要重视自己做过的模块&#xff0c;…

阿里云飞天系统的技术架构(转)

阿里云有以下五大优势&#xff1a;中国万网&#xff0c;提供虚拟主机托管的服务&#xff0c;而且还提供域名等服务&#xff0c;其客户群非常庞大。淘宝、阿里巴巴&#xff08;内部称&#xff1a;B2B&#xff09;、支付宝等其他子公司&#xff1a;有大量的数据分析业务&#xff…

Jenkins 流水线 获取git 分支列表_基于Jenkins的DevOps流水线实践

讲师介绍课程寄语我认为Jenkins是对我这些年运维经验的总结&#xff0c;起初我们运维同学都是编写脚本完成一些自动化的操作。而有了Jenkins我们可以将我们的运维经验与Jenkins设计理念融合完成自动化运维平台。全程最佳实践&#xff0c;Pipeline as Code&#xff0c;打通DevOp…

Java微服务:蛋糕是骗人的,但您不能忽略它

构建微服务实际上意味着什么&#xff1f; 通过微服务框架的眼光回答 忽略微服务的趋势已变得不可能。 有些人会说这只是另一个难以忍受的流行语&#xff0c;而另一些人会背诵打破巨石的优势或采取逆势方法并关注负面因素。 在本文中&#xff0c;我们将深入了解我们拥有的框架…

隐马尔科夫模型C#类库调用示例

[c-sharp] view plaincopyprint?using System; using Splash; namespace SplashCheck { class TestHMMCS { enum Weather { Sunny, Cloudy, Rainy }; // 隐藏状态&#xff08;天气&#xff09; enum Seaweed { Dry, Dryish, Damp, Soggy }…

芯片,开源,数学,计算机

近代数学好像没什么数学定理是中国人命名的&#xff0c;有也是凤毛麟角是广泛意义上的华人命名的。开源Linux内核好像也没有几行代码是中国人贡献的&#xff0c;通用CPU芯片美帝的&#xff0c;计算机美帝发明的&#xff0c;内存/硬盘/显示器&#xff0c;三星台湾造。20年前我大…

C#之继承

本文意在巩固基础知识&#xff0c;并不是对其进行深入剖析&#xff0c;如若对各位高手没有什么作用&#xff0c;请绕过。本文为原创文&#xff0c;所有示例均是博主测试过的&#xff0c;欢迎大家批评指正&#xff0c;如有转载请标明出处&#xff0c;谢谢。继承、封装和多态是面…

python的requests模块功能_python中requests模块的使用方法

本文实例讲述了python中requests模块的使用方法。分享给大家供大家参考。具体分析如下&#xff1a; 在HTTP相关处理中使用python是不必要的麻烦&#xff0c;这包括urllib2模块以巨大的复杂性代价获取综合性的功能。相比于urllib2,Kenneth Reitz的Requests模块更能简约的支持完整…

ODPS技术架构及应用实践

《程序员》杂志2014年10月刊《凌云》云计算大数据阿里云ODPShadoop摘要&#xff1a;ODPS是分布式的海量数据处理平台&#xff0c;提供了丰富的数据处理功能和灵活的编程框架。本文从ODPS面临的挑战、技术架构、Hadoop迁移到ODPS、应用实践注意点等方面带领我们初步了解了ODPS的…

ssh,scp带密码操作

1、远程执行&#xff0c;带密码参数 sshpass 安装命令&#xff1a; yum install sshpass 执行命令&#xff1a; sshpass -p "mima" ssh rootlocalhost --------参数小写p&#xff0c;密码mima 2、非22端口 ssh -p 9062 111.111.111…

junit 测试 dao_JUnit测试Spring Service和DAO(带有内存数据库)

junit 测试 dao这篇文章描述了如何为Spring Web Application的Services和DAO实现JUnit测试。 它建立在Spring MVC-Service-DAO-Persistence Architecture Example的基础上 。 从Github的Spring-Web-JPA-Testing目录中可以找到该示例。 提醒 测试装置 –固定状态&#xff0c;用…

C++判断文件夹是否存在

判断文件夹是否存在一、判断文件夹是否存在&#xff1a; 1.用CreateDirectory(".//FileManege",NULL);如果文件夹FileManege不存在&#xff0c;则创建。 2.或者if(_access(".//FileManege",0)-1)&#xff0c;表示FileManege不存在。 3.或者…

ODPS MR开发 WordCount

参考&#xff1a; ODPS初始篇--客户端配置和使用&#xff1a;http://blog.itpub.net/26613085/viewspace-1327313/ odps dship客户端使用&#xff1a;http://blog.itpub.net/26613085/viewspace-1328434/ 有了上面两篇文章&#xff0c;就可以使用ODPS的客户端&#xff1b;使用O…

跨域设置

# 参考&#xff1a; https://blog.csdn.net/linzi1994/article/details/82724429 https://www.cnblogs.com/ShaunChen/p/5998800.html# 配置详解&#xff1a; # 跨域设置 CORS_ORIGIN_ALLOW_ALL True # 允许所有域名 CORS_ALLOW_CREDENTIALS True # 允许获取cookie CORS_UR…

kdb q介绍

Q起源Kx systems公司的创始人之一Arthur Whitney在2003年研发了列式数据库KDB和它的操作语言q。q也可以写成Q。设计之初&#xff0c;q语言要做到简洁&#xff0c;高效和富表达性。 q的起源受到多种语言的启示。包括APL、LISP和函数式编程。 APL是一个向量语言&#xff0c;所以…

mysql多大_洞悉MySQL底层架构:游走在缓冲与磁盘之间

提起MySQL&#xff0c;其实网上已经有一大把教程了&#xff0c;为什么我还要写这篇文章呢&#xff0c;大概是因为网上很多网站都是比较零散&#xff0c;而且描述不够直观&#xff0c;不能系统对MySQL相关知识有一个系统的学习&#xff0c;导致不能形成知识体系。为此我撰写了这…

odps新手上路之安装Eclipse开发环境

只看楼主更多操作楼主 发表于: 2014-11-07—本帖被 亮伟 执行取消精华操作(2014-11-27)—准备工作&#xff1a;登录阿里云官网&#xff0c;开通odps服务。创建一个odps的project。安装odps的客户端&#xff0c;具体的方法见 传送门下载Eclipse并解压缩。建议到官网上下载。作…