🎓 A1Learner
🔍
0 of 47 lessons completed

Julia Atomics and Locks

Atomics and locks are tools that keep shared integer state correct when many threads update it. An atomic integer updates exactly, and a lock lets only one thread at a time into a guarded section.

An atomic integer counts exactly

A loop adds one to an atomic integer one hundred times, and the final count is exact.

function atomic_count()
    counter = Threads.Atomic{Int}(0)
    Threads.@threads for i in 1:100
        Threads.atomic_add!(counter, 1)
    end
    return counter[]
end
println(atomic_count())

A lock guards one shared total

A loop adds the numbers from 1 to 10 inside a lock, and the guarded total is exact.

function locked_total()
    lk = ReentrantLock()
    shared = [0]
    Threads.@threads for i in 1:10
        lock(lk) do
            shared[1] += i
        end
    end
    return shared[1]
end
println(locked_total())

An atomic integer adds a full range

A loop adds each number from 1 to 20 to an atomic integer, and the final total is exact.

function atomic_total()
    counter = Threads.Atomic{Int}(0)
    Threads.@threads for i in 1:20
        Threads.atomic_add!(counter, i)
    end
    return counter[]
end
println(atomic_total())

Example

function combined()
    counter = Threads.Atomic{Int}(0)
    lk = ReentrantLock()
    shared = [0]
    Threads.@threads for i in 1:50
        Threads.atomic_add!(counter, 1)
    end
    Threads.@threads for i in 1:20
        lock(lk) do
            shared[1] += i
        end
    end
    println(counter[])
    println(shared[1])
end
combined()

Key points

  • Atomic integer: a Threads.Atomic{Int} value holds one integer that threads can update exactly.
  • Use Threads.atomic_add! to add an integer to an atomic integer.
  • ReentrantLock: a lock is a guard that allows only one thread at a time inside its section.
  • Use lock(lk) do ... end to guard shared state with a lock.
  • Integer updates: this lesson uses integer updates only, because integer addition gives the same total in any order.

In this example, an atomic integer counts fifty updates, then a lock guards a sum of the numbers from 1 to 20, and the example prints the count and then the sum.

Note

the do block form releases the lock for you when its section ends.

Try it Yourself

Edit the code, then press Run.

Running is simulated · JuliaHub

Exercise

Which tool lets only one thread at a time into a guarded section?