Locking a specific value using ReentrantLock

Is it possible to lock a specific value using ReentrantLock()

Example:

struct Person
    name::String
    age::Int64
    number::Int64
end

nancy = Person("Nancy", 34, 12345678)

# What I do now
lk = ReentrantLock()
lock(lk) do 
    nancy.age = 35
end

# What I want to do
lk_age = ReentrantLock(nancy.age)
lock(lk_age) do 
    nancy.age = 35
end

Let’s say that we have multiple threads running, and one of them want to increase the age of Nancy. The only value in the struct that we want to change is the age, since the name and the number is static. Is it possible to only hold a lock on the age-value, to prevent the need for other threads to lock when they only really need access to values that never change?

You could always store a reentrant lock in Person, and just lock that specific lock whenever any operation is done with to the age field. This would mean that it only locks for the person in question for operations on the field in question.

Otherwise you could probably create some kind of ResourceLock where you kept a set of all currently locked resources, and if the new resource being locked is not in it is added to the set, if not you have to wait. When a resource is unlocked it is just removed from the set. Though I guess there will be more things to consider than I mention here, and unless you really want this I think the first option seems easier.

How do I do that? Do I specify which item to lock when I create the lock?
If I understand correctly, when you lock a lock, then the whole system is locked right? So then nothing is accessible, right?

Maybe something like this could work

struct Person
    name::String
    age::Int64
    number::Int64
    lock::ReentrantLock
end

nancy = Person("Nancy", 34, 12345678)

# This only locks the nancy lock, so any other person wont be affected. 
# And it will only affect other threads accessing nancy if they also try to aquire the lock first
# which they would then only (and always) do when reading or writing the age field
lock(nancy.lock) do 
    nancy.age = 35
end

Not really (at least in my understanding). When you lock a lock, anything else trying to aquire that specifik lock is prohibited from that. But your other threads can still go about and do anything as long as they dont try to aquire an already locked lock.

1 Like

You can then use a setting and getting function in the code like this:

function set_age!(p::Person, age)
    lock(p.lock) do
        p.age = age
    end
end

function get_age(p::Person)
    lock(p.lock) do
        return p.age
    end
end 

Then the locking of this field is done in a reusable way

1 Like

I would advise reading at least the introduction of

https://juliafolds.github.io/data-parallelism/