代码之家  ›  专栏  ›  技术社区  ›  Luke

同步块中的原子变量

  •  0
  • Luke  · 技术社区  · 8 年前

    我指的是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();
        }
      }
    }
    
    5 回复  |  直到 8 年前
        1
  •  2
  •   Kayaman    8 年前

    当然不是。但是如果你在做一个涉及线程安全类的操作,比如 AtomicInteger 和其他变量(即使它们是其他变量) AtomicIntegers ),你可能需要。

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

    在将手动同步与 java.util.concurrent 类,因为并发类很可能提供了一个更干净的解决方案。

        2
  •  0
  •   Amir    8 年前

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

        3
  •  0
  •   assylias    8 年前

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

    您的第二个代码有一个问题: int 变量是公共的,所以不能保证总是从 同步的

        4
  •  0
  •   Ruslan Akhundov    8 年前

    在你的例子中,这两种方法都可以使用 AtomicInteger 没有 synchronized 或者你的 MyIntegerWrapper 在…内 同步的 .

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

    选择什么还取决于变量被不同线程修改的频率。 AtomoicInteger 使用 比较并设定 (或只是cas)内部操作,而不是同步。与进入相比,CAS被认为更快,因为它的开销更小 同步的 块,但在高争用情况下(当有许多线程试图同时修改此变量时) 同步的 块可以更有效。而且 同步的 为jvm提供了一些优化空间,比如锁粗化。所以在选择时要记住这一点 原子整数 结束 同步的 .

        5
  •  0
  •   Vyacheslav Babanin    8 年前

    在第一个示例中,使用两个同步。

    原子整数实现” Non-blocking synchronization algorithm "

    确切地 自由点 允许单个线程饥饿但保证系统范围内吞吐量的算法。

    该算法借助机器指令工作。例如,在x86(自80486以来)和安腾体系结构中,这是作为比较与交换(CMPXCHG)指令实现的。

    你的关键词“synchronized”是多余的,甚至不允许工作 无锁 算法具有很好的优势。

    因此,在您的情况下,不要使用synchronized block,而是使用AtomicInteger。

    推荐文章