Skip to content

Commit a0ed4c6

Browse files
[docs] add section on data races to parallelism tutorial (#4072)
1 parent 1535ecb commit a0ed4c6

File tree

1 file changed

+78
-8
lines changed

1 file changed

+78
-8
lines changed

docs/src/tutorials/algorithms/parallelism.md

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,17 +87,87 @@ julia> ids
8787
For more information, read
8888
[PSA: Thread-local state is no longer recommended](https://julialang.org/blog/2023/07/PSA-dont-use-threadid/).
8989

90-
### Thread safety
90+
### Data races
9191

92-
When working with threads, you must avoid race conditions, in which two
93-
threads attempt to write to the same variable at the same time. In the above
94-
example we avoided a race condition by using `ReentrantLock`. See the
95-
[Multi-threading](https://docs.julialang.org/en/v1/manual/multi-threading/)
92+
When working with threads, you must avoid data races. A data race occurs when
93+
multiple threads access the same variable at the same time, at least one thread
94+
modifies the variable, and the order of the reads and writes are not properly
95+
coordinated.
96+
97+
Here's an example of a data race:
98+
````julia
99+
julia> begin
100+
x = Ref(0)
101+
Threads.@threads for i in 1:Threads.nthreads()
102+
for i in 1:1_000
103+
x[] += 1
104+
end
105+
end
106+
x[]
107+
end
108+
1106
109+
````
110+
The expected answer is `4_000` (because there are four threads each incrementing
111+
1,000 times), but the actual result is much smaller. Moreover, the result is
112+
non-deterministic; if we re-ran this code, we would get a different value each
113+
time.
114+
115+
We got the wrong answer because multiple threads are reading and writing `x`
116+
at the same time without coordination. For example, the following sequence
117+
could occur:
118+
119+
* Assume `x[]` currently has a value of `3`
120+
* Thread A reads `x[]` to get `3`
121+
* Thread B reads `x[]` to get `3`
122+
* Thread A writes `x[] = 3 + 1 = 4`
123+
* Thread B writes `x[] = 3 + 1 = 4`
124+
* The final value of `x[]` is `4`
125+
126+
The write from Thread A is overwritten, and so the value of `x[]` has increased
127+
by `1` instead of `2`.
128+
129+
Similar to the earlier `ids` example, we can fix this data race using a
130+
`ReentrantLock`. The lock ensures that only one thread can update (read and then
131+
write) `x` at a time. Now we get the correct answer:
132+
````julia
133+
julia> begin
134+
x = Ref(0)
135+
l = ReentrantLock()
136+
Threads.@threads for i in 1:Threads.nthreads()
137+
for i in 1:1_000
138+
lock(l) do
139+
x[] += 1
140+
end
141+
end
142+
end
143+
x[]
144+
end
145+
4000
146+
````
147+
148+
With the lock, the sequence of events goes something like:
149+
150+
* Assume `x[]` currently has a value of `3`
151+
* Thread A acquires the lock
152+
* Thread A reads `x[]` to get `3`
153+
* Thread B asks for the lock, but is denied because A is currently using it
154+
* Thread A writes `x[] = 3 + 1 = 4`
155+
* Thread A releases the lock
156+
* Thread B acquires the lock
157+
* Thread B reads `x[]` to get `4`
158+
* Thread B writes `x[] = 4 + 1 = 5`
159+
* Thread B releases the lock
160+
* The final value of `x[]` is `5`
161+
162+
See the [Multi-threading](https://docs.julialang.org/en/v1/manual/multi-threading/)
96163
section of the Julia documentation for more details.
97164

98-
JuMP models are not thread-safe. Code that uses multi-threading to
99-
simultaneously modify or optimize a single JuMP model across threads may error,
100-
crash Julia, or silently produce incorrect results.
165+
### JuMP models are not thread-safe
166+
167+
An object is thread-safe if it can be modified by separate threads without
168+
causing a data race. JuMP models are not thread-safe. Code that uses
169+
multi-threading to simultaneously modify or optimize a single JuMP model
170+
across threads may error, crash Julia, or silently produce incorrect results.
101171

102172
For example, the following incorrect use of multi-threading crashes Julia:
103173
```julia

0 commit comments

Comments
 (0)