static表示所有对象的值的一个副本,volatile表示所有线程的值的一个副本,这样说对吗?

无论如何,一个static变量的值也将是所有线程的一个值,那么我们为什么要 Select volatile呢?

推荐答案

在Java中声明static变量,意味着无论创建了多少个类对象,都只有一个副本.即使不创建Objects,也可以访问该变量.然而,线程可能有它的本地缓存值.

当变量是volatile而不是static时,每Object将有一个变量.所以,从表面上看,它似乎与正常变量没有区别,但与static完全不同.但是,即使有Object个字段,线程也可以在本地缓存变量值.

这意味着,如果两个线程同时更新同一对象的一个变量,并且该变量未声明为volatile,则可能存在这样的情况:其中一个线程的缓存中有一个旧值.

即使通过多个线程访问static个值,每个线程也可以有其本地缓存副本!为了避免这种情况,可以将变量声明为static volatile,这将迫使线程每次读取全局值.

但是,对于正确的同步而言,volatile%不是替身!
例如:

private static volatile int counter = 0;

private void concurrentMethodWrong() {
  counter = counter + 5;
  //do something
  counter = counter - 5;
}

多次同时执行concurrentMethodWrong可能会导致计数器的最终值不同于零

private static final Object counterLock = new Object();

private static volatile int counter = 0;

private void concurrentMethodRight() {
  synchronized (counterLock) {
    counter = counter + 5;
  }
  //do something
  synchronized (counterLock) {
    counter = counter - 5;
  }
}

或者使用AtomicInteger级.

Java相关问答推荐

Proguard配置以保留具有参数的注释的成员

Gmail Javi API批量处理太多请求

我们如何直接使用kerminldap服务票证来通过ldap进行身份验证并形成LDAP上下文

如何使用解析器组合子解析Java数组类型签名?

BiPredicate和如何使用它

使用Java Streams API比较两个不同的Java集合对象和一个公共属性

为什么我们仍然需要实现noArgsConstructor如果Java默认提供一个非参数化的构造函数?''

Android Studio—java—在onBindViewHolder中,将断点和空白添加到BackclerView中

需要一个找不到的jakarta.sistence.EntityManager类型的Bean

如何获得执行人?

把一条整型短裤和两条短裤装成一条长的

在Java中将int[]矩阵添加到ArrayList中,但出现错误

STREAMS减少部分结果的问题

在使用具有不同成本的谓词调用allMatch之前对Java流进行排序会带来什么好处吗?

如何在Java中使用正则表达式拆分字符串

在WHILE()循环初始化部分中声明和初始化变量的Java语法?

JOOQ:批处理CRUD操作使用动态表定义,如何?

javax.crypto-密码对象-提供者服务是如何工作的?

ReturnedRect在升级后反转

如何使用java区分以下结果