An unclean way would be to add a lock to the special type in the array. Something like:
mutable struct NewAtomicMutable
lck::ReentrantLock
a::Int
b::Int
end
cvec = [NewAtomicMutable(Base.ReentrantLock(), 0, 0) for _ in 1:5]
for i in 1:10
idx = rand(eachindex(cvec))
lock(cvec[idx].lck)
try
cvec[idx].a += 1
cvec[idx].b += 2
finally
unlock(cvec[idx].lck)
end
end
The last loop atomically modifies the data fields of the mutable struct.
This is not very clean, and can be abstracted to a new Array type. Perhaps someone knows about an existing implementation (sounds like a construct which would in occasional use).
Actually, for strictly update operations, a SpinLock might be more performant:
mutable struct NewAtomicSpin
lck::Base.Threads.SpinLock
a::Int
b::Int
end
cvec = [NewAtomicSpin(Base.Threads.SpinLock(), 0, 0) for _ in 1:5]
(can be used with the same update loop)