Synchronized 和volatile

来源:互联网 发布:bt离线下载软件 编辑:程序博客网 时间:2024/05/29 09:29

一、同步关键字Synchronized

使用方式有两种:
修饰方法,即对某一个方法进行同步。
普通方法,调用这个方法的对象进行加锁。
静态方法:是对这个类进行加锁。
修饰代码块,即只对一部分代码进行同步。
括号中的变量也分为普通变量和静态变量两种。
普通变量和普通方法线程是获取对象的锁。
静态方法和静态变量线程是获取class的锁。

Jvm是如何实现加锁的:
在Jvm中每个Object和class都关联着一个监视器monitor。
monitor就是实现锁的方式。
一旦一段代码被嵌入到一个synchronized关键字中,意味着放入了监视区域,首先进入监视区域entermonitor,执行方法,退出监视区域leavemonitor。
entermonitor就是获得某个Object或者class的锁
leavemonitor就是释放某个Object或者class的锁

二、关键字Volatile
原子性: 对任意单个变量的读写具有原子性。
但类似于++这种符合操作不具有原子性。
可见性: 由volatile修饰的变量,
在写变量的时候,可以保证及时的刷新进主内存。
在读变量的时候,保证读取的值来自主内存,还不是线程缓存。
(对一个volatile变量的读,总是能看到(任意线程)对这个
volatile变量的最后的写入)

Volatile的写和锁的释放有相同的语义
Volatile的读与锁的获取有相同的语义
在内存语义上表述为:
当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。
当读一个volaitle变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。
锁的内存语义:
当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。
当线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区代码必须要从主内存中去读取共享变量。

Volatile的读写 可以实现线程之间的通信。
线程A写一个volatile变量,实质上是线程A向接下来将要读这个volatile变量的某个线程发出了消息
线程B读一个volatile变量,实质上是线程B接收了之前某个线程发出的消息
线程A写一个volatile变量,随后线程B读这个volatile变量,这个过程实质上是线程A在向线程B通过主内存发送消息

Volatile 写-读建立的happens-before关系
A线程写一个volatile变量后,B线程读同一个volatile变量。
A线程在写volaitle变量之前所有可见的共享变量,在B线程读同一个volatile之后,将立即变得对线程B可见。(线程B读一个volatile变量之后,写线程A在这个volatile变量之前所有可见的共享变量的值都将立即变得对线程B可见)

0 0