对象共享
synchronized 设定原子性确定临界区 + 内存可见性
要解决如下问题
防止一个线程在使用对象状态而另一个线程在修改对象状态;且当一个线程修改了对象状态后,对其他线程可见。
 
可见性
多线程情况下的读写,无法保证在执行读操作时能够看到其他线程写入的值 --- 同步机制解决
造成可见性的原因之一:指令重排序 ---- 产生失效数据
 
在32为机器执行double和long的问题
Jvm会拆分为两个32为的操作,在读取或写入时可能存在问题
读取到某个数的的高32位和另一个数的低32位     ---- (volatile)
 
加锁和可见性
加锁不仅是局限于互斥行为,还包括内存可见性。所有执行读写操作的线程都必须在同一个锁上同步。(happen-before)
 
volatile
保证变量更新通知其他线程,volatile变量确定为共享变量,不会进行指令重排序。而且不会被寄存器缓存。
volatile可见性,A线程写入一个volatile变量,B线程读取该变量。在写入之前对A可见的所有变量的值,在B读取变量以后对B也可见。
使用情况:在需要对可见性进行复杂判断时,不适用;适用于:自身状态可见性,确保引用状态的可见性,标识一些重要的程序生命周期事件的发生(init/destroy)
volatile不能保证递增操作的原子性。
加锁操作即可保证原子性又能保证可见性,volatile只能保证可见性
 
volatile使用总结
对变量的写入操作不依赖于变量当前值,或者确保单线程更新变量
该变量不会与其他状态变量一起纳入不变性条件中
(不变性条件:
对象创建以后其状态就不能修改
对象的所有域都是final类型
对象是正确创建的(在对象的创建期间,this引用没有溢出)
)
在访问变量时不需要加锁
 
发布与逸出
发布:对象能在当前作用域以外的地方使用
逸出:对象在不该被发布时发布了(如对象构建完成前)
不要在构造其中使用this引用逸出。
 
线程封闭
不使用共享数据 --- 线程封闭
单线程内访问数据
当某个对象封闭在一个线程中时,将自动实现线程安全,即使被封闭的对象本身不是线程安全的
(JDBC -- Connection,局部变量,ThreadLoacal)
 
Ad-hoc线程封闭
维护线程封闭完全由程序承担。,访问volatile变量时如可以保证时单线程写入,则可以实现特殊的线程封闭,且volatile可保证可见性,其他线程可以看到最新值
 
栈封闭
局部变量
 
不变性
不可变对象一定线程安全
 
final域
构造不可变对象
保证对象初始化过程的安全性,共享final对象时无需同步。
如果final类型域指向的是可变的对象,在访问这些域所指向对象的状态时仍然需要同步
 
安全的发布模式
在静态初始化函数中初始化一个对象引用。
将对象引用保存在volatile类型的域或者AtomicReferance对象中
将对象引用保存到某个正确构造对象的final类型域中
将对象引用保存到一个由锁保护的域中
保证安全发布的容器
Vector / synchronizedList
Hashtable / synchronizedMap / ConcurrentMap
CopyOnWriteArrayList / CopyOnWriteArraySet / synchronizedSet
BlockingQueue / ConcurrentLinkedQueue
其他数据传输机制:Future / Exchanger
 
事实不可变对象
发布以后的状态不会再改变状态的对象
 
对象的发布需求取决于可变性:
不可变对象可以任意的发布
事实不可变对象需要安全的发布
可变对象需要安全的发布,并且线程安全必须用某个锁保护起来
 
并发程序中使用共享对象的常用策略
线程封闭 --- 对象只有一个线程持有
只读共享 --- 可变对象/不可变对象的多线程读取
线程安全共享 --- 在线程安全内部实现同步
保护对象 --- 加锁

Java并发编程杂记(2)的更多相关文章

  1. Java并发编程杂记(1)

    高并发: cpu -- 缓存 -- 内存 资源利用率 公平性 便利性   生活举例 --- 串行任务中的异步性:我在烧水的时候看书 --- 平衡点   安全性问题 --- 产生竞态条件 共享数据 -- ...

  2. 【Java并发编程实战】----- AQS(四):CLH同步队列

    在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形.其主要从两方面进行了改造:节点的结构与节点等待机制.在结构上引入了头 ...

  3. 【Java并发编程实战】----- AQS(三):阻塞、唤醒:LockSupport

    在上篇博客([Java并发编程实战]----- AQS(二):获取锁.释放锁)中提到,当一个线程加入到CLH队列中时,如果不是头节点是需要判断该节点是否需要挂起:在释放锁后,需要唤醒该线程的继任节点 ...

  4. 【Java并发编程实战】----- AQS(二):获取锁、释放锁

    上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...

  5. 【Java并发编程实战】-----“J.U.C”:CLH队列锁

    在前面介绍的几篇博客中总是提到CLH队列,在AQS中CLH队列是维护一组线程的严格按照FIFO的队列.他能够确保无饥饿,严格的先来先服务的公平性.下图是CLH队列节点的示意图: 在CLH队列的节点QN ...

  6. 【Java并发编程实战】-----“J.U.C”:CountDownlatch

    上篇博文([Java并发编程实战]-----"J.U.C":CyclicBarrier)LZ介绍了CyclicBarrier.CyclicBarrier所描述的是"允许一 ...

  7. 【Java并发编程实战】-----“J.U.C”:CyclicBarrier

    在上篇博客([Java并发编程实战]-----"J.U.C":Semaphore)中,LZ介绍了Semaphore,下面LZ介绍CyclicBarrier.在JDK API中是这么 ...

  8. 【Java并发编程实战】-----“J.U.C”:ReentrantReadWriteLock

    ReentrantLock实现了标准的互斥操作,也就是说在某一时刻只有有一个线程持有锁.ReentrantLock采用这种独占的保守锁直接,在一定程度上减低了吞吐量.在这种情况下任何的"读/ ...

  9. Java并发编程:volatile关键字解析

    Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...

随机推荐

  1. java8-计算时间差的方法

    一.简述 在Java8中,我们可以使用以下类来计算日期时间差异: 1.Period 2.Duration 3.ChronoUnit 二.Period类 主要是Period类方法getYears(),g ...

  2. kubernetes haproxy+keepalive实现master集群高可用

    前言 master的HA,实际是apiserver的HA.Master的其他组件controller-manager.scheduler都是可以通过etcd做选举(--leader-elect),而A ...

  3. Netty实战:设计一个IM框架

    来源:逅弈逐码 bitchat 是一个基于 Netty 的 IM 即时通讯框架 项目地址:https://github.com/all4you/bitchat 快速开始 bitchat-example ...

  4. Git - Git版本库相关操作

    创建Git版本库 如下命令实现在“E:\GitCode\01_TestGit”路径下,01_TestGit项目的Git版本库. $ cd E: #将当前目录转到E盘下 $ cd GitCode    ...

  5. 关于C# webapi ,接口返回字符串和json格式 ,返回值中有反斜杠

    最近遇到一个比较郁闷的问题,记录一下 写了一个接口,想返回json 数据,但是返回值中总是带有反斜杠... ,下面来看原因 首先,配置 webapi的路由 App_Start 文件夹下 ,WebApi ...

  6. django中使用pandas Django-pandas

    在django中使用pandas操作django的ORM查询出来的QuerySet对象,可以使用插件django-pandas. 截止教程书写时间,django-pandas已发布到0.6.1. 依赖 ...

  7. jenkins-pipeline里使用docker命令

    在jenkins的pipeline里,就是jenkinsfile文件里,如果希望调用docker来构建镜像,需要进行以下配置! tools{}里添加docker是失败的,这个我找了很多资料,最后需要e ...

  8. Spring Boot 2 + Thymeleaf:表单字段绑定、表单提交处理

    Spring Boot中Thymeleaf对表单处理的一些用法:(1)使用th:field属性:进行表单字段绑定(2)使用ids对象:一般用于lable配合radio或checkbox使用(3)表单提 ...

  9. Notification 弹出一个通知在桌面右下角

    if (!("Notification" in window)) { //alert("This browser does not support desktop not ...

  10. Linux-3.14.12内存管理笔记【建立内核页表(1)】

    前面已经分析过了Intel的内存映射和linux的基本使用情况,已知head_32.S仅是建立临时页表,内核还是要建立内核页表,做到全面映射的.下面就基于RAM大于896MB,而小于4GB ,切CON ...