`

Volatile与sychronized

    博客分类:
  • Java
 
阅读更多

    在使用 volatile 关键字时要慎 重,并不是只要简单类型变量使用 volatile 修饰,对这个变量的所有操作都是原来操作,当变量的值由自身的上一个决定时,如 n=n+1 n++ 等, volatile 关键字将失效,只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如 n = m + 1 ,这个就是原级别的。所以在使用 volatile 关键时一定要谨慎,如果自己没有把握,可以使用 synchronized 来代替 volatile

Volatile: 用在多线程,同步变量。 线程为了提高效率,将某成员变量 ( A) 拷贝了一份(如 B ),线程中对 A 的访问其实访问的是 B 。只在某些动作时才进行 A B 的同步。因此存在 A B 不一致的情况。 volatile 就是用来避免这种情况的。 volatile 告诉 jvm 它所修饰的变量不保留拷贝,直接访问主内存中的(也就是上面说的 A)

Synchronized: 同步方法或变量的同时也锁定了类

 

 

深入了解 synchronized 及对象锁

2008-09-09 10:361 , Synchronized 锁定的是对象而非函数或代码。

2 , 每个 Object 只有一把锁 (Lock) 与之关联,当进行到 Synchronized 语句或函数的时候,这把锁就会被当前的线程( thread )拿走,其他的( thread )再去访问的时候拿不到锁就被暂停了

3, 只有当 Synchronized 的是同一个对象的才是线程安全的( thread-safe

:

    1) public Synchronized void method1 : 锁住的是该对象 , 类的其中一个实例 , 当该对象 ( 仅仅是这一个对象 ) 在不同线程中执行这个同步方法时 , 线程之间会形成互斥 . 达到同步效果 , 但如果不同线程同时对该类的不同对象执行这个同步方法时 , 则线程之间不会形成互斥 , 因为他们拥有的是不同的锁 .

    2) Synchronized(this){ //TODO } 同一

 

    3) public Synchronizedstatic void method3 : 锁住的是该类 , 当所有该类的对象 ( 多个对象 ) 在不同线程中调用这个 static 同步方法时 , 线程之间会形成互斥 , 达到同步效果 , 但如果多个线程同时调用 method1 , method3, 则不会引互斥 , 具体讲看最后讲解 .

    4) Synchronized(Test.class){ //TODo} 同三

 

    5) synchronized(o) {} 这里面的 o 可以是一个任何 Object 对象或数组 , 并不一定是它本身对象或者类 , 谁拥有 o 这个锁 , 谁就能够操作该块程序代码 .

 

这里面 1) 2) 是线程安全的 , 1) 3) , 2) 3) 他们所拥有的锁不一样 , 故不是同步的 , 不是线程安全的 .

 

 

最后 , synchronized 所同步的代码应该尽量少 . 如果没有必要同步的就不要列为其中

     联想到数据库的并发控制

假如有如下操作

    1) 从数据库中读取数据

    2) 修改数据

    3) 提交数据

解决方案一

1) 读取数据

synchronized(XXX)

{

    2) 修改数据

    3) 提交数据

解决方案二

synchronized(XXX)

{

    1) 读取数据

    2) 修改数据

    3) 提交数据

}

 

解决方案三

synchronized(XXX)

{

     3) 提交数据

}

 

这里面到底用哪一种方案视具体情况而定 , 要注意的是 synchronized( 同步 ) 的代价 , 开销是很大的 .

 

 

 

volatile 关键字有什么用?

  恐怕比较一下 volatile synchronized 的不同是最容易解释清楚的。 volatile 是变量修饰符,而 synchronized 则作用于一段代码或方法;看如下三句 get 代码:

int i1;                          int geti1() {return i1;}

volatile int i2;              int geti2() {return i2;}

int i3; synchronized     int geti3() {return i3;}

 

   geti1() 得到存储在当前线程中 i1 的数值。多个线程有多个 i1 变量拷贝,而且这些 i1 之间可以互不相同。换句话说,另一个线程可能已经改变了它线程内的 i1 值,而这个值可以和当前线程中的 i1 值不相同。事实上, Java 有个思想叫“主”内存区域,这里存放了变量目前的“准确值”。每个线程可以有它自己的变量拷贝,而这个变量拷贝值可以和“主”内存区域里存放的不同。因此实际上存在一种可能:“主”内存区域里的 i1 值是 1 ,线程 1 里的 i1 值是 2 ,线程 2 里的 i1 值是 3 ——这在线程 1 和线程 2 都改变了它们各自的 i1 值,而且这个改变还没来得及传递给“主”内存区域或其他线程时就会发生。

  而 geti2() 得到的是“主”内存区域的 i2 数值。用 volatile 修饰后的变量不允许有不同于“主”内存区域的变量拷贝。换句话说,一个变量经 volatile 修饰后在所有线程中必须是同步的;任何线程中改变了它的值,所有其他线程立即获取到了相同的值。理所当然的, volatile 修饰的变量存取时比一般变量消耗的资源要多一点,因为线程有它自己的变量拷贝更为高效。

  既然 volatile 关键字已经实现了线程间数据同步,又要 synchronized 干什么呢?呵呵,它们之间有两点不同。首先, synchronized 获得并释放监视器——如果两个线程使用了同一个对象锁,监视器能强制保证代码块同时只被一个线程所执行——这是众所周知的事实。但是, synchronized 也同步内存:事实上, synchronized 在“主”内存区域同步整个线程的内存。因此,执行 geti3() 方法做了如下几步:

1. 线程请求获得监视 this 对象的对象锁(假设未被锁,否则线程等待直到锁释放)

2. 线程内存的数据被消除,从“主”内存区域中读入( Java 虚拟机能优化此步。。。 [ 后面的不知道怎么表达 , ]

3. 代码块被执行

4. 对于变量的任何改变现在可以安全地写到“主”内存区域中(不过 geti3() 方法不会改变变量值)

5. 线程释放监视 this 对象的对象锁

  因此 volatile 只是在线程内存和“主”内存间同步某个变量的值,而 synchronized 通过锁定和解锁某个监视器同步所有变量的值。显然 synchronized 要比 volatile 消耗更多资源。

分享到:
评论

相关推荐

    volatile与synchronized的区别

    volatile与synchronized的区别,锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility)

    Java volatile与AQS锁内存可见性

    从JUC中的AQS引入,讲解Java volatile与AQS锁内存可见性

    C#中volatile与lock用法

    本文实例讲述了C#中volatile与lock用法,分享给大家供大家参考。具体分析如下: 一、C#中volatile volatile是C#中用于控制同步的关键字,其意义是针对程序中一些敏感数据,不允许多线程同时访问,保证数据在任何访问...

    Volatile详解,深入学习Volatile

    详细说明 并举例说明了VOlatile的作用及用法,特别是嵌入式程序员要注意的

    java volatile 关键字实战

    java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java ...

    Const与Volatile

    详细介绍Const与Volatile的相同与不同

    C语言中关键字volatile的作用

    C语言中关键字volatile的作用,使用说明和例子

    volatile的使用

    一般说来,volatile用在如下的几个地方: 1、中断服务程序中修改的供其它程序检测的变量需要加volatile; 2、多任务环境下各任务间共享的标志应该加volatile; 3、存储器映射的硬件寄存器通常也要加volatile说明,...

    从汇编角度理解volatile

    一般对于volatile的解释是这样的:将变量定义为volatile可以防止编译器对变量进行优化,每次均从内存中访问变量,而不是寄存器。既然让编译器优化可以提高访问速度,那为什么又要不用它以及什么时候不用它?其实主要...

    volatile变量详解

    容易忽略的变量声明,但是很重要 volatile的作用: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.

    const和volatile分析

    const和volatile分析 这个分析得很好 面试 找工作 必备的

    volatile的用法讲解

    volatile的用法讲解,讲得很详细,希望能帮助到大家

    const,extern,static,volatile的使用

    const,extern,static,volatile的使用

    volatile的使用方法

    C程序中volatile关键字的使用.方法及其例程介绍。

    Java线程:volatile关键字

    主要讲述java线程volatile关键字

    单片机C语言中volatile的作用

    本文给大家介绍了单片机C语言中volatile的作用。

    volatile的用法

    volatile的用法,在写代码正确使用volatile,正确理解volatile的用法,增强代码的健壮性

    volatile_unsigned_int

    讲述了volatile_unsigned_int地址映射的使用说明。

    volatile源码分析1

    前言Java中volatile这个热门的关键字,在面试中经常会被提及,在各种技术交流群中也经常被讨论,但似乎讨论不出一个完美的结果,带着种种疑惑,准备从JVM、

Global site tag (gtag.js) - Google Analytics