【java并发编程实战】第二章:对象的共享
1.重要的属性
可见性,不变性,原子性
1.1可见性
当一个线程修改某个对象状态的时候,我们希望其他线程也能看到发生后的变化。
在没有同步的情况下,编译器和处理器会对代码的执行顺序进行重排。以提高效率。重排后的顺序是不可预知的,所以在多线程中无法对执行结果进行判断
看下面的代码
public class NoVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread {
@Override
public void run() {
while (!ready) {
System.out.println(">>>");
}
System.out.println(1/number);
}
}
public static void main(String[] args) {
new ReaderThread().start();
number = 1;
ready = true;
}
}
上面的执行结果可能会一直执行下去,也可能抛错。我们期望number=1以后,ready=true执行,最后输出1/1=1,由于重排,可能导致ready先初始化,然后线程读取到的还是ready=true,number=0.导致异常.
最低安全性:线程在没有同步的情况下可能会得到失效的值,但是至少这个值是之前某个线程设置的,而不是随机值。但有一个例外,看下面
其中提到了一个很有趣的非原子的64位操作
jvm内存模型规定,变量的读写操作都要原子性,但是有个例外,非volatile修饰的long和double这64位的操作,jvm允许将64位的读写操作分成2个32位的操作,就可能导致读取到的某个值的高32位和另外一个值的低32位。
除非用volatile或者锁保护起来。
1.1.1 volatile
基础
1.弱同步机制,volatile更新后的值将会通知其他线程。
2.变量修饰后,jvm或处理器不会对其进行指令重排。
3.不会被缓存在寄存器或者其他处理器看不到的地方。所以读取的值都是最新的。
其中与加锁不同的是,加锁可以保证原子性和可见性,但是volatile修饰后只能保证可见性。
1.1.2 threadlocal
threadlocal是为了防止可变的单实例变量或全局变量进行共享。jdbc就是采用了threadlocal。
threadlocal这里只描述场景和并发的关系。需要独立篇幅进行原理分析。
1.1.3
解决并发问题的另一个解决方案,不变形对象。不可变对象一定是线程安全的。
对象不可变的满足条件:
①对象创建后就不可修改
②对象的所有域都是final修饰
③对象是正确创建的,创建期间没有this溢出被其他地方修改。
final修饰的List,Map等都是可以继续添加元素。可以采用Collections.unmodifiableXXX()。其实它的原理不过是实现一个Map接口。重写了put和remove等修改的时候进行异常抛出的操作。
private static class UnmodifiableMap<K,V> implements Map<K,V>, Serializable {
private static final long serialVersionUID = -1034234728574286014L;
private final Map<? extends K, ? extends V> m;
UnmodifiableMap(Map<? extends K, ? extends V> m) {
if (m==null)
throw new NullPointerException();
this.m = m;
}
// 省略
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
public V remove(Object key) {
throw new UnsupportedOperationException();
}
public void putAll(Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException();
}
}
【java并发编程实战】第二章:对象的共享的更多相关文章
- JAVA并发编程实战---第二章:线程安全性
对象的状态是指存储在状态变量中的数据.对象的状态可能包括其他依赖对象的域.例如HashMap的状态不仅存储在HashMap本身,还存储在许多Map.Entry对象中.对象的状态中包含了任何可能影响其外 ...
- Java并发编程实战4章
第4章主要介绍如何构造线程安全类. 在设计线程安全类的过程中,需要包含以下三个基本要素: 找出构成对象状态的所有变量. 找出约束状态变量的不变性条件. 建立对象状态的并发访问管理策略. 构造线程安全类 ...
- Java并发编程实战3章
1.同步包括两方面:原子性和可见性. 2.可见性:因为在多线程程序中,如果没有采用正确的同步,有些线程就会得到失效数据. Java内存模型要求,变量的读取操作和写入操作都必须是原子操作,但对于非vol ...
- Java并发编程实战---第六章:任务执行
废话开篇 今天开始学习Java并发编程实战,很多大牛都推荐,所以为了能在并发编程的道路上留下点书本上的知识,所以也就有了这篇博文.今天主要学习的是任务执行章节,主要讲了任务执行定义.Executor. ...
- 《Java并发编程实战》/童云兰译【PDF】下载
<Java并发编程实战>/童云兰译[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062521 内容简介 本书深入浅出地介绍了Jav ...
- 《java并发编程实战》笔记
<java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为: Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...
- [书籍翻译] 《JavaScript并发编程》 第二章 JavaScript运行模型
本文是我翻译<JavaScript Concurrency>书籍的第二章 JavaScript运行模型,该书主要以Promises.Generator.Web workers等技术来讲解J ...
- Java并发编程实战 03互斥锁 解决原子性问题
文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和 ...
- Java并发编程实战 04死锁了怎么办?
Java并发编程文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 前提 在第三篇 ...
- Java并发编程实战——读后感
未完待续. 阅读帮助 本文运用<如何阅读一本书>的学习方法进行学习. P15 表示对于书的第15页. Java并发编程实战简称为并发书或者该书之类的. 熟能生巧,不断地去理解,就像欣赏一部 ...
随机推荐
- redis 对cmd的操作
这个是原子递增的知识点: 关于list部分: 利用lpush命令, rpush命令, lrange命令,对列表操作 此前 我已经 在列表(list)中 插入了 部分 元素了 关于集合set 部分 首先 ...
- MapReduce执行jar练习
1.用程序生成输入文件1.txt和2.txt 生成程序源码如下: https://www.cnblogs.com/jonban/p/10555364.html 2. 上传文件到hdfs文件系统 创建 ...
- left join后面加上where条件浅析
select a.*,b.* from table1 a left join table2 b on b.X=a.X where XXX 如上:一旦使用了left join,没有where条件时,左表 ...
- RestKit ,一个用于更好支持RESTful风格服务器接口的iOS库
简介 RestKit 是一个用于更好支持RESTful风格服务器接口的iOS库,可直接将联网获取的json/xml数据转换为iOS对象. 项目主页: RestKit 最新示例: 点击下载 注意: 如果 ...
- Spring框架进阶3
Spring框架进阶3 测试spring_jdbc和spring对事务的管理 先配置相应的pom <?xml version="1.0" encoding="UTF ...
- Java的按值传递和按引用传递解说
在网上看到的一个帖子解释Java的按值传递和按引用传递,感觉挺全面,就转过来,以供以后学习参考: 1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下: public clas ...
- Selenium页面加载策略
https://blog.csdn.net/wkb342814892/article/details/81611737 https://blog.csdn.net/ouyanggengcheng/ar ...
- python简介,数据类型,input,if语句
1. python的起源 python的创始人为吉多·范罗苏姆(龟叔Guido van Rossum),1989年的圣诞节期间,龟叔为了在阿姆斯特丹打发时间 决心开发一个新的脚本程序解释器,作为A ...
- 实用jquery插件
jquery toast 一个弹窗插件 jquery.form.min.js 一个Ajax表单插件
- JavaSE 第二次学习随笔(String的坑 + ==)
String 类是一个final类, 其内部是使用的 private final char value[]; 来存储内容, 其既可以当作一个基本类型来使用也可以当作一个类来使用;final 类(Str ...