java - 针对volatile的解决方法?
阿神
阿神 2017-04-18 09:22:40
0
4
456
package basic; public class TestVolatile { public volatile static int count = 0; public static void increase() { try { // 延迟10毫秒,使得结果明显 Thread.sleep(10); count++; } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { for (int i = 0; i < 10000; i++) { new Thread(new Runnable() { @Override public void run() { TestVolatile.increase(); } }).start(); } System.out.println("期望运行结果:10000"); System.out.println("实际运行结果:" + TestVolatile.count); } }

代码如下,由于volatile的read and load操作并不是原子性的,它只保证了从主内存读到栈内存的值是最新的,因此上述代码运行结果并不是语气的10000。
问题:
1.既然volatile并没有保证原子性,为什么还要使用它?
2.JDK中针对volatile的这种弊端,还做了哪些设计来弥补这一缺憾?

阿神
阿神

闭关修行中......

reply all (4)
迷茫

volatileIt can avoid register optimization, and Java also comes with a barrier. Although it cannot prevent competition, it can be used for competition-free synchronization across threads.
If there is still competition for data, you should consider the Atomic data type. However, it is best to avoid competition as much as possible, because competition will reduce concurrency.

    PHPzhong

    @FreeBirdLjj has already summarized the general function of

    volatile, and I would like to add a few more points

    1. volatileThe function is to ensure the memory visibility of variables between different threads and the atomicity of reading and writing to a single volatile variable. The main method is to insert a specific type of memory barrier when the compiler generates an instruction sequence.

    2. volatileThe visibility of memory is mainly achieved by prohibiting reordering (compiler reordering, processor reordering), ensuring that the cache expires in time, and ensuring that the cache is flushed into the main memory in a timely manner

    3. The semantics of reading and setting a singlevolatilevariable are equivalent to
      public synchronized A getA();
      public synchronized void setA();

      迷茫

      During the execution of a task, in order to improve efficiency, the initialization process is sometimes reordered, which may make the program unstable in the case of multi-thread concurrency. Use volatile to prevent reordering.

      memory = allocate(); //1:分配对象的内存空间 ctorInstance(memory); //2:初始化对象 instance = memory; //3:设置instance指向刚分配的内存地址

      Between 2 and 3 in the above three lines of pseudocode, may be reordered (on some JIT compilers, this reordering actually occurs, see "Out-of-order writes" in Reference 1 for details part). The execution timing after reordering between 2 and 3 is as follows:

      memory = allocate(); //1:分配对象的内存空间 instance = memory; //3:设置instance指向刚分配的内存地址 //注意,此时对象还没有被初始化! ctorInstance(memory); //2:初始化对象

      If multiple threads access concurrently at this time, the object may not be initialized yet.
      The volatile keyword will prevent this optimization and ensure that it will be executed in the order of the first piece of code every time.
      Source: http://www.infoq.com/cn/articles/double-checked-locking-with-delay-initialization

        左手右手慢动作

        What you need is [Lock].

          Latest Downloads
          More>
          Web Effects
          Website Source Code
          Website Materials
          Front End Template
          About us Disclaimer Sitemap
          php.cn:Public welfare online PHP training,Help PHP learners grow quickly!