Martin Odersky:努力保持简单

Bul*_*ula 6 logic asynchronous scala

我正在观看马丁·奥德斯基(Martin Odersky)在斯卡拉课程中自己推荐的演讲,我很好奇它的一个方面

var x = 0
async { x = x + 1 }
async { x = x * 2 }
Run Code Online (Sandbox Code Playgroud)

所以我得到它,如果第一个语句首先执行然后第二个执行,它可以给2:

x = 0;
x = x + 1;
x = x * 2; // this will be x = 2
Run Code Online (Sandbox Code Playgroud)

我得到它如何给1:

x = 0;
x = x * 2;
x = x + 1 // this will be x = 1
Run Code Online (Sandbox Code Playgroud)

但是怎么能得到0呢?声明是否可能根本不执行?

很抱歉这么简单的问题,但我真的很困惑

Pau*_*her 9

您需要考虑交错执行.请记住,CPU需要先读取值,x然后再对其进行操作.想象一下:

  1. 线程1读取x(读0)
  2. 线程2读取x(读0)
  3. 线程1写x + 1(写1)
  4. 线程2写入x * 2(写入0)


Spa*_*key 5

我知道这已经得到了解答,但也许这仍然有用:

将其视为一系列原子操作.处理器一次进行一次原子操作.

这里我们有以下内容:

  • 读x
  • 写x
  • 加1
  • 乘以2

保证以下两个序列以"自身内"的顺序发生:

  • 读x,加1,写x
  • 读x,乘2,写x

但是,如果您并行执行它们,则相对于另一个序列任何其他原子操作执行每个原子操作的时间是随机的,即这两个序列交错.

其中一个可能的执行顺序将产生0,由Paul Butcher在答案中给出

这是我在互联网上找到的插图:

在此输入图像描述

每个蓝色/紫色块都是一个原子操作,您可以看到如何根据块的顺序获得不同的结果

要解决此问题,您可以使用关键字" synchronized "

我的理解是,如果你在同一个对象中用同步标记两个代码块(例如两个方法),那么每个块在执行时将拥有该对象的锁,这样另一个块就不能被执行而第一个没有完了.但是,如果在两个不同的对象中有两个同步块,则它们可以并行执行.

  • 请原谅我的迂腐,但同步不会使代码块成为原子.它的作用是声称与对象相关的内在锁.所以它会让你互相排斥一些声称具有相同内在锁定的其他代码,但这与使其成为原子的不同. (2认同)