共享(shared)(多个线程访问)和可变(mutable)状态
synchronized提供同步机制
synchronized同步:独占的加锁机制
volatile同步:
显示锁同步:explicit lock
原子变量同步
非线程安全的操作:
非原子操作[cpu有哪些原子操作]
结果状态依赖前一个状态
程序原子方式的操作:
程序原子方式:代码不一定需要全部执行完毕,须保证其它程序不同时进入同一段代码(同一个环境)或者使用同一个竞争的变量(如:ActomicLong)
程序一般通过加锁来确保程序原子性操作
JAVA提供内置锁来提供原子性,synchronized(提供同步代码块),每个java对象都可以用作一个实现同步的锁,这些锁被称为内置锁或监视锁
JAVA的内置锁是一种互斥锁
锁的重入: 当一个线程尝试获取已经由自己获取的锁时,是会成功的
如子类覆盖父类的synchronized,调用super方法
同步和锁的区别:锁实现了互斥,同步=互斥+内存可见性
同步还有一个重要的是内存可见性:
我们不仅希望可以互斥操作,而且希望确保一个线程修改了对象状态之后,其它线程可以看到发生的变化
(synchronized代表同步)
一种常见的加锁约定:
将所有的可变状态都封装在对象内部,并通过对象的内置锁对所有访问可变状态的代码路径进行同步,使该对象上不会发生并发访问。
许多线程安全的类都使用了这种方式,如Vector和其他的同步集合类
活跃性和性能
应该尽量将不影响共享状态且执行时间较长的操作从同步代码块中分离出去 以及不要使用阻塞的操作和注意循环内的操作
但获取锁和释放锁需要消耗资源和时间,不应把代码分的太细
<!-------------------------------------------------------------------------------------------------------!>
3.1 可见性
如:线程有自己的私有内存,线程将变量写到内存中,其它线程还是从自己线程内存中读取
即写线程的操作对读线程不可见 + p28(42)(重排序)
只要数据在多个线程之间共享,就需要正确的同步
3.1.2 非原子的64位操作 p29(43)
java内存模型要求:变量的读操作和写操作都必须是原子性的,(变量:任何变量?ps:查看java内存模型)
对于非volatile类型的long和double变量,JVM允许将64位的读操作或写操作分解为2个32位的操作
3.1.3 加锁和可见性
为什么在访问某个共享可变变量时,需要所有线程在同一个锁上 => 这样保证 同步代码块的变量是 可见性的
这种锁:称之为同步锁 ?
(即锁释放的时候,线程会把线程中的值写入到内存中 ?)
3.1.4 volatile变量
volatile变量不会和其它内存操作进行重排序,volatile不会被缓存在寄存器或其它处理器不可见的地方。
访问volatile变量时不会执行加锁操作,不建议过度以来volatile,因为会使代码更加脆弱
仅当volatile变量可以简化代码实现以及同步策略的验证时,才应该使用它们。p31(45)
3.2 发布和逸出
发布: 使对象能够在当前作用域之外的代码中使用。
逸出: 当某个不该发布的对象被发布时(如对象构造完成之前发布对象),这种情况成为逸出
(fixme:逸出问题其实是另一种控制作用域的方法)
p33(47)这可能是sla对字段等精确作用域控制的原因
3.2.1 隐式的(构造函数中)使this引用逸出,如:构造器中创建并发布内部类,构造器中启动一个线程
3.3 线程封闭
fixme:类似ThreadLocal,局部变量
没有共享数据,每个线程使用自己的数据
3.3.1 Ad-hoc线程封闭(比较脆弱,不推荐使用)
:维护线程封闭性的职责完全由程序(这里程序指语言特性)来实现。
在volatile变量上有一种特殊的线程封闭,保持一个线程写,多个线程读,则写线程可以进行读取-修改-写入
(即把变量封闭到了写线程,fixme:这里的volatile变量如果是引用也可以??应该不可以)
3.3.2 栈封闭:线程内部自己的局部变量
3.3.3 ThreadLocal类: currentThread => ThreadDataMap,
当某个频繁执行的操作需要一个临时对象,例如一个缓冲区,而同时又希望避免每次执行时重新分配该临时对象,即可以使用ThreadLocal
ThreadLocal变量类似全局变量,降低了代码的重用性,并在类之间引入了隐含的耦合性
3.4 不变性 immutable object
不可变对象一定是线程安全的:
当满足以下条件时,对象才是不可变的:=> sla的不可变对象
1. 对象创建以后状态就不能修改
2. 对象的所有域都是final的
3. 对象是正确创建的(对象创建期间,this引用没有逸出)
3.4.1 final
3.4.2 volatile
3.1.3 加锁和可见性
3.1.4 volatile 变量 比 synchronized 更轻量级
(中文翻译的根本看不懂,以下是自己翻译和理解)
When thread A writes to a volatile variable and subsequently thread B reads that same variable, the values of all variables that were visible to A prior to writing to the volatile variable become visible to B after reading the volatile variable. So from a memory visibility perspective, writing a volatile variable is like exiting a synchronized block and reading a volatile variable is like entering a synchronized block.
-- ps: cpu 的读和写是原子操作的
thread A对volatile 变量进行写入,随后thread B读取此变量的值,在A写入之前,所有值对A是可见的(即A直接访问的是(进程的)内存,不是自己线程的内存区域),在B读入之后,对B是可见的。所以什 么是内存可见性,写入一个volatile变量 类似 退出一个synchronized block,读入一个 volatile变量 类似 进入一个synchronized block .
退出一个synchronized block,即还没有释放锁,其它线程 读写不了,
进入一个synchronized block,即还没有获得所,线程读不了
总结:volatile 原理是使用了CPU读 写的原子性,并强制线程从进程内存中读取,而不是线程自己的内存。
引用: http://www.iteye.com/magazines/131
- 对引用变量和大部分基本类型变量(除long和double之外)的读写是原子的。
- 对所有声明为volatile的变量(包括long和double变量)的读写是原子的。
java.util.concurrent包中的一些类提供了一些不依赖同步机制的原子方法
相关推荐
java并发编程实践笔记java并发编程实践笔记java并发编程实践笔记java并发编程实践笔记
java并发编程实战pdf学习笔记 总结了重要的知识点
java并发编程实践笔记资料.pdf
《Java并发编程实践》一书的个人读书笔记。主要列举包括各个章节的关键知识点,便于反复阅读和知识复习掌握。
Java是最先支持多线程的开发的语言之一,Java从一开始就支持了多线程能力,因此Java开发者能常遇到上面描述的...这也是我想为Java并发技术而写这篇系列的原因。作为对自己的笔记,和对其他Java开发的追随者都可获益的。
当调用 start 启动线程时 Java 虚拟机会调 用该类的 run方法。 那么该类的 run() 方法中就是调用了 Runnable 对象的 run() 方法。 我 们可以继承重写Thread 类,在其 start 方法中添加不断循环调用传递过来的 ...
的管理,这种分离还在不同事务间划分了自然的分界线,在程序出现错误时可以很方便地进行恢复,还有利于提高程序的并发性。围绕任务执行来管理应用程序时,第一步要指明一个清晰的任务边界,理想情况下,任务是 独立...
线程安全就是对共享的、可变的状态进行管理,对象的状态就是它的数据,换句话说就是在不可控制的并发访问中保护数据。
使用java.util.concurrent类库构造安全的并发应用程序的基础。共享其实就是某一线程的数据改变对其它线程可见,否则就会出现脏数据。
在实践中,委托是创建线程安全类最有效的策略之一:用已有的线程安全类来管理所 有状态即可。
java中没有提供任何机制,来安全是强迫线程停止手头的工作,Thread.stop和 Thread.suspend方法存在严重的缺陷,不能使用。程序不应该立即停止,应该采用中断这种协作机制来处理,正确的做法是:先清除当前进程中的...
Linux面试专题及答案+ActiveMQ消息中间件面试专题+Java基础面试题+MySQL性能优化的21个最佳实践+微服务面试专题及答案+深入理解java虚拟机+设计模式面试专题及答案+开源框架面试专题及答案+并发编程及答案+Spring...
Java 并发学习笔记: 进程和线程, 并发理论, 并发关键字, Lock 体系, 原子操作类, 发容器 & 并发工具, 线程池, 并发实践 Java是一种面向对象的编程语言,由Sun Microsystems于1995年推出。它是一种跨平台的...
Java语言从第一版本开始内置了对多线程的支持,这一点在当年是非常了不起的,但是当我们对并发编程有了更深刻的认识和更多的实践后,实现并发编程就有了更多的方案和更好的选择。本文是对并发编程的核心理论做了下小...
Java并发编程.pdf JAVA核心知识点整理.pdf Java高级架构知识点整理.pdf Java高级架构面试知识点整理.pdf JVM与性能优化知识点整理.pdf MySQL性能调优与架构设计解析文档.pdf Nginx入门到实战.pdf springCloud笔记....
学习线程介绍Java多线程学习PDF格式Java并发编程的艺术.pdf JAVA并发编程实践.pdf图解Java多线程设计模式-第2版.pdf代码code1是《 Java并发编程的艺术》的源码ThreadDesignPatterns是《图解Java多线程设计模式》第1...
Java并发体系知识导图笔记.xmind JVM和性能优化.xmind JVM面试专题及答案.pdf kafka知识导图笔记.xmind Kafka面试专题及答案.pdf Linux面试专题及答案.pdf memcached面试专题及答案.pdf MongoDB面试专题及答案.pdf ...
2022java面试题、JVM面试题、多线程面试题、并发编程、Redis面试题、MySQL面试题、Java2022面试题、Netty面试题 一、内容概览 本次分享的资源涵盖了Java面试的各个方面,从基础知识到高级技术,从数据库到框架应用...
《实战Java高并发程序设计》笔记和源码笔记《实战Java高并发程序设计》中有很多代码范例,适合初学者通过实践入门并发编程,这本书有个问题就是前面的代码都用JDK7,第六章开始又用JDK8了笔者精心制作相关笔记并整理...