Java volatile关键字的用途是什么?

Java volatile关键字的用途是什么?,java,multithreading,keyword,volatile,Java,Multithreading,Keyword,Volatile,在今天的工作中,我遇到了Java中的volatile关键字。我不太熟悉它,我发现 鉴于那篇文章详细解释了该关键字,您是否曾经使用过它,或者您是否曾经看到过可以正确使用该关键字的情况?“…volatile修饰符保证任何读取字段的线程都会看到最近写入的值。”-Josh Bloch 如果您正在考虑使用volatile,请仔细阅读有关原子行为的软件包。 上的Wikipedia帖子显示volatile正在使用。“…volatile修饰符保证任何读取字段的线程都会看到最近写入的值。”-Josh Bloch

在今天的工作中,我遇到了Java中的
volatile
关键字。我不太熟悉它,我发现

鉴于那篇文章详细解释了该关键字,您是否曾经使用过它,或者您是否曾经看到过可以正确使用该关键字的情况?

“…volatile修饰符保证任何读取字段的线程都会看到最近写入的值。”-Josh Bloch

如果您正在考虑使用volatile,请仔细阅读有关原子行为的软件包。

上的Wikipedia帖子显示volatile正在使用。

“…volatile修饰符保证任何读取字段的线程都会看到最近写入的值。”-Josh Bloch

如果您正在考虑使用volatile,请仔细阅读有关原子行为的软件包。


维基百科上的帖子显示了volatile正在使用中。

当然,是的。(不仅在Java中,而且在C#中)有时您需要获取或设置一个值,该值保证在给定平台上是原子操作,例如int或boolean,但不需要线程锁定的开销。volatile关键字允许您确保在读取值时获得的是当前值,而不是一个缓存值,该缓存值是在另一个线程上写入而过时的。

绝对是。(不仅在Java中,而且在C#中)有时您需要获取或设置一个值,该值保证在给定平台上是原子操作,例如int或boolean,但不需要线程锁定的开销。volatile关键字允许您确保在读取值时获得的是当前值,而不是刚被另一个线程写入而过时的缓存值。

volatile
具有内存可见性的语义。基本上,
volatile
字段的值在写入操作完成后对所有读卡器(特别是其他线程)都可见。如果没有volatile,读者可以看到一些未更新的值

回答您的问题:是的,我使用
volatile
变量来控制某些代码是否继续循环。循环测试
volatile
值,如果
为true
则继续。通过调用“停止”方法,可以将条件设置为
false
。循环看到
false
,并在stop方法完成执行后测试值时终止

我极力推荐的书“,”很好地解释了
volatile
。这本书是由同一个人写的,他写了问题中引用的IBM文章(事实上,他在文章的底部引用了他的书)。我使用的
volatile
就是他的文章所称的“模式1状态标志”


如果你想了解更多关于引擎盖下的工作原理,请阅读。如果你想超越这一层次,请阅读一本优秀的计算机体系结构书籍,如《缓存一致性和缓存一致性》。volatile具有内存可见性的语义。基本上,
volatile
字段的值在写入操作完成后对所有读卡器(特别是其他线程)都可见。如果没有volatile,读者可以看到一些未更新的值

回答您的问题:是的,我使用
volatile
变量来控制某些代码是否继续循环。循环测试
volatile
值,如果
为true
则继续。通过调用“停止”方法,可以将条件设置为
false
。循环看到
false
,并在stop方法完成执行后测试值时终止

我极力推荐的书“,”很好地解释了
volatile
。这本书是由同一个人写的,他写了问题中引用的IBM文章(事实上,他在文章的底部引用了他的书)。我使用的
volatile
就是他的文章所称的“模式1状态标志”


如果你想了解更多关于引擎盖下的工作原理,请阅读。如果您想超越这一级别,请查阅一本优秀的计算机体系结构书籍,如,并阅读有关缓存一致性和缓存一致性的内容。

使用
volatile
的一个常见示例是使用
volatile boolean
变量作为终止线程的标志。如果您已经启动了一个线程,并且希望能够安全地从另一个线程中断它,那么可以让该线程定期检查一个标志。要停止,请将标志设置为true。通过设置标志
volatile
,您可以确保正在检查它的线程在下次检查它时会看到它已被设置,而无需使用
synchronized
块。

使用
volatile
的一个常见示例是使用
volatile boolean
变量作为终止线程的标志。如果您已经启动了一个线程,并且希望能够安全地从另一个线程中断它,那么可以让该线程定期检查一个标志。要停止,请将标志设置为true。通过设置标志
volatile
,您可以确保正在检查它的线程在下次检查它时会看到它已被设置,而无需使用
synchronized
块。

是的,只要您希望多个线程访问可变变量,就必须使用volatile。这不是很常见的用例,因为通常您需要执行多个原子操作(例如,在修改变量之前检查变量状态),在这种情况下,您将使用同步块。

是的,当您希望多个线程访问可变变量时,必须使用volatile。这不是很常见的用例,因为通常您需要
public class Foo extends Thread {

  private volatile boolean close = false;

  public void run() {
    while(!close) {
      // do work
    }
  }
  public void close() {
    close = true;
    // interrupt here if needed
  }
}
package io.netty.example.telnet;

import java.util.ArrayList;
import java.util.List;

public class Main {

    public static volatile  int a = 0;
    public static void main(String args[]) throws InterruptedException{

        List<Thread> list = new  ArrayList<Thread>();
        for(int i = 0 ; i<11 ;i++){
            list.add(new Pojo());
        }

        for (Thread thread : list) {
            thread.start();
        }

        Thread.sleep(20000);
        System.out.println(a);
    }
}
class Pojo extends Thread{
    int a = 10001;
    public void run() {
        while(a-->0){
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Main.a++;
            System.out.println("a = "+Main.a);
        }
    }
}
    package io.netty.example.telnet;

    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.atomic.AtomicInteger;

    public class Main {

        public static volatile  AtomicInteger a = new AtomicInteger(0);
        public static void main(String args[]) throws InterruptedException{

            List<Thread> list = new  ArrayList<Thread>();
            for(int i = 0 ; i<11 ;i++){
                list.add(new Pojo());
            }

            for (Thread thread : list) {
                thread.start();
            }

            Thread.sleep(20000);
            System.out.println(a.get());

        }
    }
    class Pojo extends Thread{
        int a = 10001;
        public void run() {
            while(a-->0){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Main.a.incrementAndGet();
                System.out.println("a = "+Main.a);
            }
        }
    }
public class Singleton {
    private static volatile Singleton _instance; // volatile variable
    public static Singleton getInstance() {
        if (_instance == null) {
            synchronized (Singleton.class) {
                if (_instance == null)
                    _instance = new Singleton();
            }
        }
        return _instance;
    }
}
public class Singleton{    
    private static Singleton _instance;   //without volatile variable
    public static Singleton getInstance(){   
          if(_instance == null){  
              synchronized(Singleton.class){  
               if(_instance == null) _instance = new Singleton(); 
      } 
     }   
    return _instance;  
    }
while (busy) {
    /* do something else */
}
busy = 0;
thread 0 prints 0
thread 1 prints 1
thread 2 prints 2
thread 3 prints 3
thread 0 prints 0
thread 1 prints 1
thread 2 prints 2
thread 3 prints 3
thread 0 prints 0
thread 1 prints 1
thread 2 prints 2
thread 3 prints 3
public class Solution {
    static volatile int counter = 0;
    static int print = 0;
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Thread[] ths = new Thread[4];
        for (int i = 0; i < ths.length; i++) {
            ths[i] = new Thread(new MyRunnable(i, ths.length));
            ths[i].start();
        }
    }
    static class MyRunnable implements Runnable {
        final int thID;
        final int total;
        public MyRunnable(int id, int total) {
            thID = id;
            this.total = total;
        }
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (true) {
                if (thID == counter) {
                    System.out.println("thread " + thID + " prints " + print);
                    print++;
                    if (print == total)
                        print = 0;
                    counter++;
                    if (counter == total)
                        counter = 0;
                } else {
                    try {
                        Thread.sleep(30);
                    } catch (InterruptedException e) {
                        // log it
                    }
                }
            }
        }
    }
}
Stopping on: 1895303906650500
Stopping on: 1895285647980000
324565439> Stopped on: 1895285648087300
Read is after write
public class VisibilityDemonstration {

private static int sCount = 0;

public static void main(String[] args) {
    new Consumer().start();
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        return;
    }
    new Producer().start();
}

static class Consumer extends Thread {
    @Override
    public void run() {
        int localValue = -1;
        while (true) {
            if (localValue != sCount) {
                System.out.println("Consumer: detected count change " + sCount);
                localValue = sCount;
            }
            if (sCount >= 5) {
                break;
            }
        }
        System.out.println("Consumer: terminating");
    }
}

static class Producer extends Thread {
    @Override
    public void run() {
        while (sCount < 5) {
            int localValue = sCount;
            localValue++;
            System.out.println("Producer: incrementing count to " + localValue);
            sCount = localValue;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                return;
            }
        }
        System.out.println("Producer: terminating");
    }
}
}
Consumer: detected count change 0
Producer: incrementing count to 1
Producer: incrementing count to 2
Producer: incrementing count to 3
Producer: incrementing count to 4
Producer: incrementing count to 5
Producer: terminating
private volatile  static int sCount = 0;
Consumer: detected count change 0
Producer: incrementing count to 1
Consumer: detected count change 1
Producer: incrementing count to 2
Consumer: detected count change 2
Producer: incrementing count to 3
Consumer: detected count change 3
Producer: incrementing count to 4
Consumer: detected count change 4
Producer: incrementing count to 5
Consumer: detected count change 5
Consumer: terminating
Producer: terminating
public class SharedObject {
    public volatile int sharedVariable = 0;
}
public class SharedObject {
    public int counter = 0;
}