volatile 和 synchronized 的比较

1,volatile
   它所修饰的变量不保留拷贝,直接访问主内存中的。
   在 Java 内存模型中,有 main memory,每一个线程也有本身的 memory (例如寄存器)。为了性能,一个线程会在本身的 memory 中保持要访问的变量的副本。这样就会出现同一个变 量在某个瞬间,在一个线程的 memory 中的值可能与另一个线程 memory 中的值,或者 main memory 中的值不一致的状况。一个变量声明为 volatile,就意味着这个变量是随时会被其余线程修改的,所以不能将它 cache 在线程memory 中。



2,synchronizedjava

      当它用来修饰一个方法或者一个代码块的时候,可以保证在同一时刻最多只有一个线程执行该段代码。缓存

     1、当两个并发线程访问同一个对象 objec t中的这个 synchronized(this) 同步代码块时,一个时间内只能有一个线程获得执行。另外一个线程必须等待当前线程执行完这个代码块之后才能执行该代码块。并发

     2、然而,当一个线程访问 object 的一个 synchronized(this) 同步代码块时,另外一个线程仍然能够访问该 object 中的非 synchronized(this)同步代码块。性能

     3、尤为关键的是,当一个线程访问 object 的一个 synchronized(this) 同步代码块时,其余线程对 object 中全部其它 synchronized(this) 同步代码块的访问将被阻塞。学习

     4、当一个线程访问 object 的一个 synchronized(this) 同步代码块时,它就得到了这个 object 的对象锁。结果,其它线程对该 object 对象全部同步代码部分的访问都被暂时阻塞。this

     5、以上规则对其它对象锁一样适用.spa

 

区别:线程

 1、volatile 是变量修饰符,而 synchronized 则做用于一段代码或方法。code

 2、volatile 只是在线程内存和“主”内存间同步某个变量的值;而 synchronized 经过锁定和解锁某个监视器同步全部变量的值。显然synchronized 要比 volatile 消耗更多资源。 对象

 3、volatile 不能保证操做的原子性。synchronized 能够保证操做的原子性。

那么请参考以下:

volatile 不能保证操做的原子性。synchronized 能够保证操做的原子性。我认为这是他们最大的区别。

此外 volatile 是变量修饰符,而 synchronized 是要修饰一段代码或者方法

 

那么volatile是干什么的呢?

volatile是变量修饰符。被它修饰的变量不会在线程中保留备份(注:能够这么理解,可是其内部机制应该仍是保留了备份的,只不过是经过特殊的机制实时的将线程中变量的值更新到i)。这样就不会出现上述线程A B 和主内存的值不同的状况。

可是注意:volatile并不能保证操做的原子性。即便只是i++,实际上也是由多个原子操做组成:read i; inc; write i,假如多个线程同时执行i++,依然可能出现写入脏数据的状况。它只不过是保证各个线程操做的是同一起内存而已。

synchronized 为何能保证操做的原子性呢?

这得从它的工做机制提及,很明显 synchronized 可以保证被它修饰的一段代码同一个时刻只被同一个线程执行。

事实上它同步代码的过程也在同步内存。

假若有以下代码:

public class Test implements Runnable{

      private int i=1;

      public void run(){

          operate();

      }


      public synchronized void operate(){

            i = 2;

     }

}

当线程A执行方法operate的时候将进行以下步骤:

1.线程请求this的锁,若是锁被其余的线程占用就进入阻塞状态直到锁被释放。

2.线程内存中缓存的数据被清除,从主内存中read/load读入最新的值。

3.synchronized内的代码块被执行,在此执行过程当中其对应的主内存不会被其余的线程使用。

4.执行完毕释放锁。

 

水平有限,如有问题请留言交流!

互相学习,共同进步 :)转载请注明出处谢谢!

相关文章
相关标签/搜索