精华内容
下载资源
问答
  • Java中设置变量值的操作,除了longdouble...而随着JVM的成熟优化,现在在多线程环境下volatile关键字的使用变得非常重要。在当前的Java内存模型下,线程可以把变量保存在本地内存(比如机器的寄存器)中,而不
          在Java中设置变量值的操作,除了longdouble类型的变量外都是原子操作,也就是说,对于变量值的简单读写操作没有必要进行同步。这在JVM 1.2之前,Java的内存模型实现总是从主存读取变量,是不需要进行特别的注意的。而随着JVM的成熟和优化,现在在多线程环境下volatile关键字的使用变得非常重要。在当前的Java内存模型下,线程可以把变量保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。要解决这个问题,只需要像在本程序中的这样,把该变量声明为volatile(不稳定的)即可,这就指示JVM,这个变量是不稳定的,每次使用它都到主存中进行读取。一般说来,多任务环境下各任务间共享的标志都应该加volatile修饰。
     
     
    Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只有当线程进入或者离开同步代码块时,才能与共享变量的原始值对比。
     
     
    volatile是一个变量修饰符,而synchronized是一个方法或块的修饰符。所以我们使用这两种关键字来指定三种简单的存取变量的方式。
     int i1;           int geti1{return i1;}
     volatile int i2;    int geti2{return i2;}
     int i3;           synchronized int geti3{return i3};
     
    geti1()当前线程中立即获取在i1变量中的值。线程可以获得变量的本地拷贝,而所获得的变量的值并不一定与其他线程所获得的值相同。特别是,如果其他的线程修改了i1的值,那么当前线程获得的i1的值可能与修改后的值有所差别。实际上,Java有一种主内存的机制,使用一个主内存来保存变量当前的正确的值。线程将变量的值拷贝到自己独立的内存中,而这些线程的内存拷贝可能与主内存中的值不同。所以实际当中可能发生这样的情况,在主内存中i1的值为1,线程1和线程2都更改了i1,但是却没把更新的值传回给主内存或其他线程中,那么可能在线程1i1的值为2,线程2i1的值却为3
     
    另一方面,geti2()可以有效的从主内存中获取i2的值。一个volatile类型的变量不允许线程从主内存中将变量的值拷贝到自己的存储空间。因此,一个声明为volatile类型的变量将在所有的线程中同步的获得数据,不论你在任何线程中更改了变量,其他的线程将立即得到同样的结果。由于线程存取或更改自己的数据拷贝有更高的效率,所以volatile类型变量在性能上有所消耗。
     
    那么如果volatile变量已经可以使数据在线程间同步,那么synchronizes用来干什么呢?两者有两方面的不同。首先,synchronized获取和释放由监听器控制的锁,如果两个线程都使用一个监听器(即相同对象锁),那么监听器可以强制在一个时刻只有一个线程能处理代码块,这是最一般的同步。另外,synchronized还能使内存同步。在实际当中,synchronized使得所有的线程内存与主内存相同步。所以geti3()的执行过程如下:
    1.线程从监听器获取对象的锁。(这里假设监听器非锁,否则线程只有等到监听器解锁才能获取对象锁)
    2.线程内存更新所有的变量,也就是说他将读取主内存中的变量使自己的变量保证有效(JVM会使用一个“脏”标志来最优化过程,使得仅仅具有“脏”标志变量被更新。详细的情况查询JAVA规范的17.9)
    3.代码块被执行(在这个例子中,设置返回值为刚刚从主内存重置的i3当前的值。)
    4.任何变量的变更将被写回到主内存中。但是这个例子中geti3()没有什么变化。
    5.线程释放对象的锁给监听器。
    所以volatile只能在线程内存和主内存之间同步一个变量的值,而synchronized则同步在线程内存和主内存之间的所有变量的值,并且通过锁住和释放监听器来实现。显然,synchronized在性能上将比volatile更加有所消耗
     
    展开全文
  • 主要为大家详细介绍了Java关键字volatile和synchronized的作用区别,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 主要介绍了javavolatile和synchronized的区别与联系的相关资料,希望通过本文能帮助到大家,让大家理解这部分内容,需要的朋友可以参考下
  • 在多线程并发编程中,免不了要使用到Volatile和Synchronized关键字,但是之前对这2个关键字的理解总是很模糊,在看完了《Java多线程编程核心技术》这本书后对多线程有了比较清晰地认识。最近在看《Java并发编程...

    在多线程和并发编程中,免不了要使用到Volatile和Synchronized关键字,但是之前对这2个关键字的理解总是很模糊,在看完了《Java多线程编程核心技术》这本书后对多线程有了比较清晰地认识。最近在看《Java并发编程实战》这本书,书中对Java的Volatile和Synchronized有很详细的介绍和剖析,让我进一步有了新的认识,在博客做个总结,记录自己的学习心得。

    、java的加锁机制通常有2种方式:用Synchronized实现同步互斥和用Lock实现加锁。
    对于一个可变的变量a,在单线程环境中执行不会遇到线程安全问题,但是当多个线程同时访问这个共享变量时,有可能一个线程读到了a的值已经被另一个线程修改,会导致线程不安全。
    为了解决这个问题,可以使用加锁机制,保住每次只有一个线程能对共享变量访问,其他线程必须排队等候。
    Volatile关键字:可见性
    Java用Volatile提供了一种稍弱的同步机制,用来确保将变量的更新操作通知到其他线程。Volatile是比Synchronized更轻量级的同步机制。
    重点
    加锁机制既可以确保可见性,又可以确保原子性;
    而Volitile变量只能确保可见性。

    展开全文
  • javavolatile和synchronized关键字都是伴随着多线程经常使用的关键字,很多然搞不清楚二者的区别,这篇文章记录下来笔者的一点认识,若有不正确的地方欢迎大家在评论区指出。 区别 volatile本质是在告诉jvm...

    概述

    java中volatile和synchronized关键字都是伴随着多线程经常使用的关键字,很多然搞不清楚二者的区别,这篇文章记录下来笔者的一点认识,若有不正确的地方欢迎大家在评论区指出。

    区别

    • volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
    • volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别
    • volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
    • volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
    • volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化

    加粗字体部分的原因如下:
    线程A修改了变量还没结束时,另外的线程B可以看到已修改的值,而且可以修改这个变量,而不用等待A释放锁,因为Volatile 变量没上锁。

    举例

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

    总结

    synchronized关键字很好理解,就是保证所修饰的变量、方法、和类同时只能被一个xx调用(这里没想好修饰词),而volatile是为了保证变量可以同时被多个线程调用,而且没有上锁,即上面提到的线程A修改了变量还没结束时,另外的线程B可以看到已修改的值,这种机制有利有弊,希望大家使用的时候一定要慎重。

    展开全文
  • volatile和synchronized都可以实现Java的同步机制,那么volatile和synchronized的区别是什么,比如作用范围等,并解释其实现原理

    volatile和synchronized的区别

    区别

    总结以下几条:
      1、从功能上,volatile是告诉jvm当前变量在寄存器中的值是不对的,需要从主存中读取;synchronized是锁定当前变量或者代码,只有当前线程可以访问,其他线程被阻塞。
      2、volatile只能修饰变量。synchronized可以修饰类、方法、静态方法、方法块。其中其修饰类、静态方法时作用的这个类的所有对象。如果子类重写父类的synchronized的方法且不加synchronized修饰,子类不会继承父类的synchronized关键字,即子类的方法默认不同步。
      3、volatile是轻量级的;synchronized是重量级的。
      4、volatile只保证有序性和可见性;synchronized保证原子性、有序性和可见性。
      5、volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。

    实现原理

    volatile如何实现可见性和有序性?
      1、可见性
      对volatile修饰的变量进行赋值修改的时候,JIT编辑器所生成汇编代码会在最后有一行:

    0x01a3de24:lock addl $0x0,(%esp);
    

    代码是什么不重要,这行代码的作用是对原值加0,是一个空操作,lock前缀指令的作用是:将当前处理器缓存行的数据写回系统内存;这个写操作会使在其他CPU或者别的内核缓存了该内存地址的数据无效。而缓存一致性协议,当其他线程操作该变量时发现其无效了,就会去系统内存去重新读取数据,这就保证了被volatile修饰的变量对所有线程可见。
      2、有序性
      这是因为volatile变量在执行赋值操作后会产生一个内存屏障,在执行到内存屏障时,其前面的所有操作都已经完成,其后面的操作不会早于内存屏障执行。
      举个例子:

    // 线程A:
    a = 1;  // volatile a = 1;
    b = 2;
    // 线程B
    while(true){
    	if(b == 2){
    		c = a;
    	...
    	}
    }
    

    变量a未被volatile修饰时,由于重排序,线程A可能先执行b=2,此时线程B运行,满足进入判断条件,对c进行了赋值,但却不是想要的1,而如果a被volatile修饰,则不会出现这个问题。

    synchronized实现原理
      sychronized实现互斥同步的原理。sychronized关键字进行编译后,会在同步块的前后形成monitorenter和monitorexit两个字节码命令。在执行monitorenter命令时,首先尝试获取sychronized指定对象的锁,如果该对象未被锁定,则当前线程获取该对象的锁,并将锁的计数器加1,相应的,执行monitorexit命令时,锁的计数器减1,减到0的时候,释放该对象的锁。如果获取该对象的锁失败,则会进入阻塞状态,直到对象锁被另一个线程释放。当然,对于同一线程,synchronized同步块时可重入的,不会出现自己把自己锁死的情况,重入时,锁计数器加1。

    展开全文
  • JAVAvolatile和synchronized的区别

    万次阅读 2018-08-07 19:45:45
    volatile和synchronized的区别 共性:volatilesynchronized都用于保证多线程中数据的安全 区别: (1)volatile修饰的变量,jvm每次都从主存(主内存)中读取,而不会从寄存器(工作内存)中读取。 而...
  • synchronized 可以确保可见性又可以确保原子性,而volatile变量只能确保可见性,例如volatile不能确保递增操作(count++)的原子性操作,但是如果用synchronized 就可以确保原子性与可见性。 ...
  • 恐怕比较一下volatile和synchronized的不同是最容易解释清楚的。volatile是变 量修饰符,而synchronized则作用于一段代码或方法;看如下三句get代码: int i1; int geti1() {return i1;} volatile int i2; int...
  • 主要介绍了java多线程中的volatile和synchronized用法分析,以实例的形式分析了在多线程中volatile和synchronized的用法区别与使用原理,具有一定的参考借鉴价值,需要的朋友可以参考下
  • 今天来说说volatile和synchronized的区别,我们都知道volatile和synchronizedjava高并发中常见的关键字。 volatile volatile具备可见性,这里仅仅指的是对其他线程的可见性,也就是允许其他线程访问的共享变量。...
  • java中的volatile和synchronized区别
  • JavaVolatile和Synchronized的区别 JMM Java Memory Model. 并发过程中如何处理可见性、原子性、有序性的问题 Runnable、Thread 并发编程中的两个关键问题 a.线程之间如何通信 wait() notify() notifyall() a) ...
  • volatile
  • javavolatilesynchronized和lock解析

    千次阅读 多人点赞 2017-03-07 21:10:34
    1、概述在研究并发程序时,我们需要了解java中关键字volatile和synchronized关键字的使用以及lock类的用法。首先,了解下java的内存模型:(1)每个线程都有自己的本地内存空间(java栈中的帧)。线程执行时,先把...
  • Java中的volatile和synchronized关键字1、volatile关键字:Volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到主内存。这样在...
  • 在开发当中使用多线程的,经常会用到synchronized和volatitle。接下来就讲讲他们的使用场景。 synchronized java关键字,方法用到这个关键字则对这个方法进行加锁。一次只能进入一个线程,其他线程只能等待或执行...
  • 面试中经常会遇到以下的问题:Java中的volatile和synchronized的区别?Java中的Lock和synchronized的区别?今天我们来深入聊聊vola...
  • Java 多线程并发编程中的volatile和synchronized关键字是Java功法中的难点,这篇博文将通过一个直观的示例讲解并发编程的道法。
  • volatile和synchronized的区别: 1.volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。 2...
  • Java 关键字volatile 和synchronized的作用

    千次阅读 2017-03-28 14:00:12
    6、synchronized和volatile的比较?  1)、volatile是线程同步的轻量级实现,所以性能比synchronized要好,并且volatile只能修饰变量,而synchronized可以修饰方法和代码块。新版本的JDK中,synchronized关键字在...
  • 原子性:同一时刻,只有一个线程...但是volatile只能修饰变量,synchronized可以修饰变量、代码块、方法(volatile保证变量可见性,synchronized保证代码块可见性)。 2.volatile用于解决变量多线程之间的可见性...
  • Java中支持多个线程可以同时访问一个对象或者对象的成员变量,也就是存在共享性。共享变量的使用存在一致性的问题,对于多线程开发中,可以使用不同级别的锁来解决它,但锁的使用也有他的优缺点。而关键字vo...
  • 这个可能是最好的对比volatile和synchronized作用的文章了。volatile是一个变量修饰符,而synchronized是一个方法或块的修饰符。所以我们使用这两种关键字来指定三种简单的存取变量的方式。  int i1; int geti1()...
  • volatile和synchronized

    万次阅读 2020-01-17 12:27:10
    Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节 码,最终需要转化为汇编...2.1 volatile的应用 在多线程并发编程中synchronized和volatile都扮演着重要的角色,volatile是轻量级的 sy...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 118,008
精华内容 47,203
关键字:

javavolatile和synchronized

java 订阅