我们可以说通过同步一段代码我们正在使包含的语句成为原子吗?

时间:2014-04-09 11:01:37

标签: java multithreading synchronization

我想澄清我的理解,如果我用synchronized(this){}语句包围一段代码,这是否意味着我正在使这些语句成为原子?

5 个答案:

答案 0 :(得分:3)

不,它不能确保您的陈述是原子的。例如,如果一个synchronized块中有两个语句,则第一个可能会成功,但第二个可能会失败。因此,结果不是“全有或全无”。但是对于多个线程,您确保没有两个线程的语句交错。换句话说:所有线程的所有语句都是严格序列化的,即使如此,也不能保证线程的所有或没有语句都会被执行。

了解Atomicity的定义方式。

这是一个示例,显示读者能够准备好已损坏的状态。因此,synchronized块不是原子地执行的(原谅我讨厌的格式化):

public class Example {

    public static void sleep() {
        try { Thread.sleep(400); } catch (InterruptedException e) {};
    }

    public static void main(String[] args) {
        final Example example = new Example(1);
        ExecutorService executor = newFixedThreadPool(2);
        try {
            Future<?> reader = executor.submit(new Runnable() { @Override public void run() {
                int value; do {
                    value = example.getSingleElement();
                    System.out.println("single value is: " + value);
                } while (value != 10);
            }});
            Future<?> writer = executor.submit(new Runnable() { @Override public void run() {
                for (int value = 2; value < 10; value++) example.failDoingAtomic(value);
            }});
            reader.get(); writer.get();
        } catch (Exception e) { e.getCause().printStackTrace();
        } finally { executor.shutdown(); }
    }

    private final Set<Integer> singleElementSet;

    public Example(int singleIntValue) {
        singleElementSet = new HashSet<>(Arrays.asList(singleIntValue));
    }

    public synchronized void failDoingAtomic(int replacement) {
        singleElementSet.clear();
        if (new Random().nextBoolean()) sleep();
        else throw new RuntimeException("I failed badly before adding the new value :-(");
        singleElementSet.add(replacement);
    }

    public int getSingleElement() {
        return singleElementSet.iterator().next();
    }
}

答案 1 :(得分:3)

不,同步和原子性是两个不同的概念。

同步意味着代码块一次最多可以由一个线程执行,但是其他线程(执行使用相同数据的其他代码)可以看到&#34; synchronized&#34内生成的中间结果;块。

Atomicity意味着其他线程看不到中间结果 - 它们会看到受原子操作影响的数据的初始或最终状态。

答案 2 :(得分:1)

不幸的是,java使用synchronized作为关键字。 Java中的synchronized块是“互斥”(“互斥”的缩写)。这是一种机制,确保一次只有一个线程可以进入该块。

互斥体只是用于在多线程程序中实现“同步”的众多工具之一:从广义上讲,同步是指用于确保线程以协调方式工作的所有技术。达到预期的效果。

原子性是Oleg Estekhin所说的。我们通常在“交易”的背景下听到它。相互排斥(即Java的synchronized)保证了小于原子性的东西:即,它保护不变量

一个不变量是关于程序状态的任何断言,它应该是“永远”真实的。例如,在玩家交换虚拟币的游戏中,游戏中的硬币总数可以是不变量。但是,如果不暂时破坏不变量,通常无法推进计划的状态。互斥的目的是确保只有一个线程 - 即正在进行工作的线程 - 可以看到临时的“破坏”状态。

答案 3 :(得分:0)

对于在该对象上使用synchronized的代码 - 是的。

对于代码,不要为该对象使用synchronized关键字 - 否。

答案 4 :(得分:0)

  

我们可以说通过同步一段代码我们正在使包含的语句成为原子吗?

你在那里迈出了一大步。原子性意味着原子操作将在一个CPU周期内完成或等效于一个CPU周期,而同步块意味着只有一个线程可以访问关键区域。处理关键区域中的代码可能需要多个CPU周期(这将使其成为非原子级)。