对象共享
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. java并发编程-12个原子类

    背景 多线程更新变量的值,可能得不到预期的值,当然增加syncronized关键字可以解决线程并发的问题. 这里提供另外一种解决问题的方案,即位于 java.util.concurrent.atomi ...

  2. python爬虫执行js代码-execjs

    一.安装模块 pip install PyExecJS execjs会自动使用当前电脑上的运行时环境(建议用nodejs,与Phantomjs) 二.简单的使用 import execjs js_ob ...

  3. js相同的正则多次调用test()返回的值却不同

    项目中文件上传需要验证文件的格式,第一次正常,第二次就验证不通过了.在验证的地方console.log()两遍,发现结果不一样 !!! 正则和文件名都没变,但是两次的验证结果不同. this.reg ...

  4. Dojo.declare使用方法详解

    ArcGIS API for JavaScript是基于dojo开发的一套API,在实际生产中,我们需要再根据自己的需求实现自定义的功能,最后抽象成接口给前端调用. 我们使用dojo的declare来 ...

  5. 从华为“鸿蒙”备胎看IT项目建设

    别误会啊,本文并不在讲大家在做IT项目建设的时候学华为做一个备胎系统,以防正主系统崩掉之后能够及时替换到备胎系统里面,不影响业务. 前段时间华为被美帝制裁,然后各家组织对华为各种限制.然而华为整体布局 ...

  6. python 部署lvs

    import paramiko ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ...

  7. 高性能go服务之高效内存分配

    高性能go服务之高效内存分配 手动内存管理真的很坑爹(如C C++),好在我们有强大的自动化系统能够管理内存分配和生命周期,从而解放我们的双手. 但是呢,如果你想通过调整JVM垃圾回收器参数或者是优化 ...

  8. 【分享】nginx负载均衡全套视频教程

    1.课件 百度网盘链接:https://pan.baidu.com/s/1On2oONVZmPwI9yIDekgRiA        提取码:c4fw 2.教程列表 3.教程下载 3.1.直接在线学习 ...

  9. 树莓派设置frpc开机启动

    1.复制frpc启动命令及配置文件到系统相应目录: $ sudo cp frpc /usr/local/bin/frpc $ sudo mkdir /etc/frpc $ sudo cp frpc.i ...

  10. (转)vue-router原理

    转载地址:https://segmentfault.com/a/1190000014822765 随着前端应用的业务功能起来越复杂,用户对于使用体验的要求越来越高,单面(SPA)成为前端应用的主流形式 ...