基本上在 Julia 上跑多執行緒不太困難,在環境中先設定好執行緒的數量,或是在執行 Julia 時增加執行緒數目。

1
julia --threads 4

如果既有的程式碼是 for 迴圈,基本上不難改。

1
2
3
Threads.@threads for i = 1:1000_000
do something()
end

但是終究會遇到要存取同一個物件的時候,這個時候就會有 race condition。

要避免 race condition 的方式就是使用 lock。

1
2
3
4
5
6
7
8
9
10
11
12
13
results = []
splock = Threads.SpinLock()

Threads.@threads for i = 1:1000_000
y = do_something()

lock(splock)
try
push!(results, y)
finally
unlock(splock)
end
end

在迴圈中計算 do_something,我們想要把計算結果儲存下來,我們將他儲存在 results 中。
這時候我們必須用一個 lock 來把要存取的資源鎖住,一開始會產生一個 SpinLock,當程式執行到 lock(splock) 的時候,如果這個 lock 可以被取用,那這個執行緒就會拿這個 lock 並且進到後續的程式區塊中。如果前面有人拿了 lock,那目前這個想拿 lock 的執行緒就得等到 lock 被釋放才可以。
當程式執行完,unlock(splock) 會將 lock 給釋放掉,這個時候其他的執行緒就可以拿這個 lock 進到程式區塊中。
如此可以保證每次操作 results 物件的只能有一個執行緒,可以避免 race condition。