Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I need a lock when only a single thread writes to a shared variable?

I have 2 threads and a shared float global. One thread only writes to the variable while the other only reads from it, do I need to lock access to this variable? In other words:

volatile float x;

void reader_thread() {
    while (1) {
        // Grab mutex here?
        float local_x = x;
        // Release mutex?
        do_stuff_with_value(local_x);
    }
}

void writer_thread() {
    while (1) {
        float local_x = get_new_value_from_somewhere();
        // Grab mutex here?
        x = local_x;
        // Release mutex?
    }
}

My main concern is that a load or store of a float not being atomic, such that local_x in reader_thread ends up having a bogus, partially updated value.

  1. Is this a valid concern?
  2. Is there another way to guarantee atomicity without a mutex?
  3. Would using sig_atomic_t as the shared variable work, assuming it has enough bits for my purposes?

The language in question is C using pthreads.

like image 662
Daniel Dickison Avatar asked May 13 '09 18:05

Daniel Dickison


1 Answers

Different architectures have different rules, but in general, memory loads and stores of aligned, int-sized objects are atomic. Smaller and larger may be problematic. So if sizeof(float) == sizeof(int) you might be safe, but I still wouldn't depend on it in a portable program.

Also, the behavior of volatile isn't particularly well-defined... The specification uses it as a way to prevent optimizing away accesses to memory-mapped device I/O, but says nothing about its behavior on any other memory accesses.

In short, even if loads and stores are atomic on float x, I would use explicit memory barriers (though how varies by platform and compiler) in instead of depending on volatile. Without the guarantee of loads and stores being atomic, you would have to use locks, which do imply memory barriers.

like image 170
ephemient Avatar answered Oct 09 '22 01:10

ephemient