在Java中的Volatile和Static区别

17 浏览
0 Comments

在Java中的Volatile和Static区别

static意味着为所有对象提供一个值的副本,而volatile意味着为所有线程提供一个值的副本,这是正确的吗?

无论如何,static变量值对于所有线程来说也是一个值,为什么我们要选择volatile呢?

admin 更改状态以发布 2023年5月24日
0
0 Comments

静态变量和易失变量的区别:

静态变量:如果两个线程(假设 t1 t2 )正在访问同一个对象并更新一个已声明为静态的变量,则表示 t1 t2 可以在其各自的高速缓存中制作相同对象的本地副本(包括静态变量),因此 t1 在其本地缓存中对静态变量所做的更新不会反映在 t2 缓存中的静态变量中。

静态变量用于对象的上下文中,其中对一个对象的更新将反映在同一类的所有其他对象中,但不用于线程的上下文中,其中对静态变量的一个线程的更新将立即反映在所有线程中(在其本地缓存)。

易失变量:如果两个线程(假设 t1 t2 )正在访问同一个对象并更新已声明为易失的变量,则表示 t1 t2 可以制作自己的本地缓存 除了已声明为易失的变量之外的对象。因此,易失变量将只有一个主要副本,这将由不同的线程更新,一个线程对易失变量所做的更新将立即反映到另一个线程中。

0
0 Comments

声明一个Java中的静态变量意味着无论创建该类的对象有多少个,都只会有一个副本。即使没有创建任何对象,该变量也可以访问。但是,线程可能具有本地缓存值。\n\n当一个变量是volatile而不是static时,每个Object都有一个变量。因此,表面上似乎与普通变量没有区别,但与静态变量完全不同。但是,即使对于Object字段,线程也可能本地缓存变量值。\n\n这意味着如果两个线程同时更新同一个Object的变量,并且该变量未声明为volatile,则可能存在一个线程在缓存中具有旧值的情况。\n\n即使通过多个线程访问一个static值,每个线程也可以拥有其本地缓存复制!为避免这种情况,可以将变量声明为static volatile,这将强制线程每次读取全局值。\n\n但是,volatile不能代替适当的同步!例如:\n\n

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

\n\n同时执行concurrentMethodWrong很多次可能会导致计数器的最终值与零不同! 为解决此问题,您需要实现锁定:\n\n

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;
  }
}

\n\n或使用AtomicInteger类。

0