Posts Tagged ‘Language Lawyer’

Locking when No One’s Looking

Monday, September 16th, 2024

You’re getting ready to start a thread. But wait! There are some variables you need to get ready before then. Those variables are read by the thread. How do you know the new values of those variables will be visible to the thread?

var = 1;
thread = std::thread([this] {
    use(var);  // Will I see "1"?
});

One conservative approach might be to obtain a lock while modifying those variables. This would make a lot of sense, particularly if those variables are typically guarded by that lock during the lifetime of the thread. At the same time, it does feel a little silly obtaining a lock that you know will never be contended, as the only other thing that would lock that mutex has not started yet.

{
    std::lock_guard lock(mutex);
    var = 1;
}
thread = std::thread([this] {
    std::lock_guard lock(mutex);  // Even without this
    use(var);
});

Modifying those variables under a lock is for-sure safe: releasing the lock after modifying will do a “release” memory barrier, ensuring all writes done will be visible. The thread reading them has not started yet, so there is no possible way anything could be reordered too early to see the release. If the thread also locks the mutex before reading those values, it is even more obviously safe.

But is any of that really needed? Intuitively it shouldn’t be needed, but memory models are notoriously tricky things, so let’s check our assumptions.

(more…)