Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Martin Odersky : Working hard to keep it simple

I was watching the talk given by Martin Odersky as recommended by himself in the coursera scala course and I am quite curious about one aspect of it

var x = 0
async { x = x + 1 }
async { x = x * 2 }

So I get that it can give 2 if if the first statement gets executed first and then the second one:

x = 0;
x = x + 1;
x = x * 2; // this will be x = 2

I get how it can give 1 :

x = 0;
x = x * 2;
x = x + 1 // this will be x = 1

However how can it result 0? Is it possible that the statement don't execute at all?

Sorry for such an easy question but I'm really stuck at it

like image 628
Bula Avatar asked May 04 '14 15:05

Bula


2 Answers

You need to think about interleaved execution. Remember that the CPU needs to read the value of x before it can work on it. So imagine the following:

  1. Thread 1 reads x (reading 0)
  2. Thread 2 reads x (reading 0)
  3. Thread 1 writes x + 1 (writing 1)
  4. Thread 2 writes x * 2 (writing 0)
like image 191
Paul Butcher Avatar answered Nov 04 '22 14:11

Paul Butcher


I know this has already been answered, but maybe this is still useful:

Think of it as a sequence of atomic operations. The processor is doing one atomic operation at a time.

Here we have the following:

  • Read x
  • Write x
  • Add 1
  • Multiply 2

The following two sequences are guaranteed to happen in this order "within themselves":

  • Read x, Add 1, Write x
  • Read x, Multiply 2, Write x

However, if you are executing them in parallel, the time of execution of each atomic operation relative to any other atomic operation in the other sequence is random i.e. these two sequences interleave.

One of the possible order of execution will produce 0 which is given in the answer by Paul Butcher

Here is an illustration I found on the internet:

enter image description here

Each blue/purple block is one atomic operation, you can see how you can have different results based on the order of the blocks

To solve this problem you can use the keyword "synchronized"

My understanding is that if you mark two blocks of code (e.g. two methods) with synchronized within the same object then each block will own the lock of that object while being executed, so that the other block cannot be executed while the first hasn't finished yet. However, if you have two synchronised blocks in two different objects then they can execute in parallel.

like image 43
SpaceMonkey Avatar answered Nov 04 '22 14:11

SpaceMonkey