# Data Races

**URL:** https://discourse.julialang.org/t/data-races/44185
**Category:** General Usage
**Tags:** multithreading
**Created:** [August 3, 2020, 12:52pm UTC](https://discourse.julialang.org/t/data-races/44185 "2020-08-03T12:52:53Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![tisztamo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tisztamo/32/16200_2.png) [@tisztamo](https://discourse.julialang.org/u/tisztamo)
#### Post date: [August 3, 2020, 12:52pm UTC](https://discourse.julialang.org/t/data-races/44185/1 "2020-08-03T12:52:53Z")

</div>

The updated multithreading docs for v"1.5" says in section [“Data-race freedom”](https://docs.julialang.org/en/v1.5/manual/multi-threading/#Data-race-freedom-1):

> …  
> Additionally, Julia is not memory safe in the presence of a data race. Be very careful about reading a global variable (or closure variable) if another thread might write to it! Instead, always use the lock pattern above when changing any data (such as assigning to a global) visible to multiple threads.
> 
> ```julia
> Thread 1:
> global b = false
> global a = rand()
> global b = true
> 
> Thread 2:
> while !b; end
> bad(a) # it is NOT safe to access `a` here!
> 
> Thread 3:
> while !@isdefined(a); end
> use(a) # it is NOT safe to access `a` here
> 
> ```

It is not exactly clear to me, what this example tries to show. (two separated issues, or a single one?)

Are the following true?

- Removing thread 3 resolves the data race.
- If both `use(a)` and `bad(a)` only reads the value of `a` then thread 2 is safe.
- I guess that `@isdefined` returns `true` before the random value is assigned to `a`, so removing thread 2 does not resolve the race.

I plan to clarify the docs, but not sure if my understanding is correct. Thank you for helping!

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [August 3, 2020, 1:09pm UTC](https://discourse.julialang.org/t/data-races/44185/2 "2020-08-03T13:09:48Z")

</div>

> [@tisztamo](#):
>
> Removing thread 3 resolves the data race.

No. Thread 1 is the only writer and the two reader threads 2 and 3 each races with 1.

> [@tisztamo](#):
>
> If both `use(a)` and `bad(a)` only reads the value of `a` then thread 2 is safe.

No. And this is exactly the point of the examples.

> [@tisztamo](#):
>
> I guess that `@isdefined` returns `true` before the random value is assigned to `a`

And no. `@isdefined` will not do that, but the assignment may happen before the value is initialized.

---

<div class="post-metadata">

### Author: ![tisztamo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tisztamo/32/16200_2.png) [@tisztamo](https://discourse.julialang.org/u/tisztamo)
#### Post date: [August 3, 2020, 1:55pm UTC](https://discourse.julialang.org/t/data-races/44185/3 "2020-08-03T13:55:33Z")

</div>

Wow, thanks!

> [@yuyichao](#):
>
> the assignment may happen before the value is initialized.

Please clarify this a bit more. What means “the value is initialized”?

Here is my current understanding:

> [@](#):
>
> `global a = rand()`

There may be a time when `a` is defined but uninitialized, so thread 3 is not safe. What about thread 2? May `b` be true before `a` gets initialized because of optimizations?

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [August 3, 2020, 2:42pm UTC](https://discourse.julialang.org/t/data-races/44185/4 "2020-08-03T14:42:09Z")

</div>

> [@tisztamo](#):
>
> May `b` be true before `a` gets initialized because of optimizations?

Yes. But not really because of optimization. Unless you also include hardware behavior in the optimization.

You seems to be thinking things in the sequential consistent model. That is not the case. In general, unless there’s explicit synchronized, you cannot expect things happens in one order for one thread to happen in the same order on another.

---

<div class="post-metadata">

### Author: ![tisztamo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tisztamo/32/16200_2.png) [@tisztamo](https://discourse.julialang.org/u/tisztamo)
#### Post date: [August 3, 2020, 8:40pm UTC](https://discourse.julialang.org/t/data-races/44185/5 "2020-08-03T20:40:03Z")

</div>

> [@Solved by yuyichao in post #4](#):
>
> You seems to be thinking things in the sequential consistent model.

I think that what I assumed was not more than processor consistency, meaning that:

> the order in which other processors see the writes from any individual processor is the same as the order they were issued. ([wp](https://en.wikipedia.org/wiki/Processor_consistency))

And although I am not familiar with the topic, it seems that modern processors guarantee something like this. E.g in [x86-TSO](https://spinroot.com/spin/Doc/course/x86_tso.pdf):

![Screenshot from 2020-08-03 22-09-38](https://global.discourse-cdn.com/julialang/original/3X/6/c/6c17f4eac78974a14b4b3e3ae743132cfb057332.png)

If that is true, then I think that thread 2 is safe in the current form of the example, when thread 1 changes the value of `b` only once. Of course “locking” this way is still not a good idea, but the question is interesting.

A similar, and maybe more realistic example that comes to my mind is a mutable struct stored in a shared variable, which one wants to change swiftly by creating an another instance and locking only while changing the reference. Is that safe, or the writes of the struct creation may arrive too late?

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [August 3, 2020, 8:54pm UTC](https://discourse.julialang.org/t/data-races/44185/6 "2020-08-03T20:54:26Z")

</div>

No, it is only the case for hardware on x86. Nothing else have that. And then of course on x86, the compiler can reorder things so you still can’t rely on it anywhere.

In general, there’s no guarantee when you write a data race. If you have a race the access have to be explicitly ordered. (Not yet supported in Julia).

---

<div class="post-metadata">

### Author: ![tisztamo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tisztamo/32/16200_2.png) [@tisztamo](https://discourse.julialang.org/u/tisztamo)
#### Post date: [August 5, 2020, 8:55am UTC](https://discourse.julialang.org/t/data-races/44185/7 "2020-08-05T08:55:05Z")

</div>

Thank you for your insights! I have created a small [PR](https://github.com/JuliaLang/julia/pull/36924/files) with the hope that it helps others to understand this.
