Java 同步块中的原子变量

Java 同步块中的原子变量,java,synchronization,synchronized,thread-synchronization,Java,Synchronization,Synchronized,Thread Synchronization,我指的是Java语言,但我认为它也可以涉及其他语言 问题是:将原子变量放入同步块中有意义吗?或者同步块不会由两个线程同时执行的事实足以保证在同步块中执行的操作是原子的?(示例1与示例2) 例1: public class SharedVariables { public static AtomicInteger i; } public class MyThread extends Thread { public void run() { synchronized(SharedV

我指的是Java语言,但我认为它也可以涉及其他语言

问题是:将原子变量放入同步块中有意义吗?或者同步块不会由两个线程同时执行的事实足以保证在同步块中执行的操作是原子的?(示例1与示例2)

例1:

public class SharedVariables {
  public static AtomicInteger i;
}

public class MyThread extends Thread {
  public void run() {
    synchronized(SharedVariables.i) {
      i.getAndIncrement();
    }
  }
}
例2:

public class MyIntegerWrapper {
  public int i;
  public void increment() {
    this.i++;
  }
}

public class SharedVariables {
  public static MyIntegerWrapper i;
}

public class MyThread extends Thread {
  public void run() {
    synchronized(SharedVariables.i) {
      i.increment();
    }
  }
}

synchronized
在您的第一个代码中不是必需的,原子变量的保证就足够了


您的第二个代码有一个问题:
int
变量是公共的,因此您不能保证总是从
synchronized
块调用它。

synchronized
在您的第一个代码中不是必需的,原子变量的保证就足够了


您的第二个代码有一个问题:
int
变量是公共的,因此您不能保证总是从
同步的
块调用它。

原子变量使用非阻塞算法(它使用比较和交换机制),所以您不应该在同步块内使用它,尽量使用原子变量以获得更好的性能。

原子变量使用非阻塞算法(它使用比较和交换机制),因此不应在同步块内使用它,尽量使用原子变量以获得更好的性能。

不是因为它本身没有。但是,如果您执行的操作涉及线程安全类,如
AtomicInteger
和其他变量(即使它们是其他
AtomicInteger
),您可能需要这样做

AtomicInteger
保证它上的操作是线程安全的和原子的,而无需执行任何操作。但是假设你一个增加一个减少另一个,它们的总和总是一样的。您有两个原子操作,但要将它们组合成单个原子操作,您需要额外的同步。只有这样,您才能确保其他线程将读取这些变量的常量和


在将手动同步与
java.util.concurrent
类相结合时,我仍然会非常小心,因为并发类很可能提供了一个更干净的解决方案。

不是由其本身提供的。但是如果您正在执行一个涉及线程安全类(如
AtomicInteger
和其他变量)的操作(即使它们是其他
原子整数
),也可能需要

AtomicInteger
保证它上的操作是线程安全的,并且是原子操作,而无需执行任何操作。但是,假设一个操作是递增的,另一个操作是递减的,它们的和总是需要相同的。您有两个原子操作,但是要将它们组合成一个原子操作,您需要额外的同步。只有这样,您才能确保其他线程将读取这些变量的常量和


在将手动同步与
java.util.concurrent
类相结合时,我仍然会非常小心,因为并发类很可能提供了一个更干净的解决方案。

在您的示例中,使用
AtomicInteger
而不使用
synchronized
或使用
MyIntegerRapper
完全可以
已同步

但在一般情况下,它取决于变量可见性范围。例如,如果您决定使用
myintegerrapper
而不是
AtomicInteger
,则必须确保没有其他方法在不同步的情况下使用它


选择什么还取决于变量被不同线程修改的频率。
AtomoicInteger
在内部使用比较和设置(或仅使用cas)操作,而不是同步。cas被认为更快,因为与输入
synchronized
块相比,开销更小,但是在高争用情况下(当有许多线程试图同时修改此变量时)
synchronized
块效率更高。而且
synchronized
为jvm提供了一些优化空间,比如锁粗化。因此,在示例中选择
AtomicInteger
而不是
synchronized

时,请记住这一点。在您的示例中,使用
AtomicInteger
而不使用
synchr是完全可以的已初始化
或您的
myintegerrapper
内部
已同步

但在一般情况下,它取决于变量可见性范围。例如,如果您决定使用
myintegerrapper
而不是
AtomicInteger
,则必须确保没有其他方法在不同步的情况下使用它


选择什么还取决于变量被不同线程修改的频率。
AtomoicInteger
在内部使用比较和设置(或仅使用cas)操作,而不是同步。cas被认为更快,因为与输入
synchronized
块相比,开销更小,但是在高争用情况下(当有许多线程试图同时修改此变量时)
synchronized
块可以更有效。而且
synchronized
为jvm提供了一些优化空间,比如锁粗化。所以在选择
AtomicInteger
而不是
synchronized

时,请记住这一点。在第一个示例中,您使用了两个同步

原子整数实现“”

确切地说,看起来是免费的算法,允许单个线程饿死,但保证系统范围内的吞吐量

此算法在机器指令的帮助下工作。例如,在x86(自80486起)和安腾体系结构中,此算法作为比较与交换(CMPXCHG)指令实现

您的关键字“synchronized”是多余的,甚至不允许工作无锁算法