我想澄清我的理解,如果我用synchronized(this){}
语句包围一段代码,这是否意味着我正在使这些语句成为原子?
答案 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周期(这将使其成为非原子级)。