Is it safe to read an integer variable that's being concurrently modified without locking?

前端 未结 12 1324
青春惊慌失措
青春惊慌失措 2020-12-02 09:03

Suppose that I have an integer variable in a class, and this variable may be concurrently modified by other threads. Writes are protected by a mutex. Do I need to protect re

相关标签:
12条回答
  • 2020-12-02 09:15

    atomic read
    As said before, it's platform dependent. On x86, the value must be aligned on a 4 byte boundary. Generally for most platforms, the read must execute in a single CPU instruction.

    optimizer caching
    The optimizer doesn't know you are reading a value modified by a different thread. declaring the value volatile helps with that: the optimizer will issue a memory read / write for every access, instead of trying to keep the value cached in a register.

    CPU cache
    Still, you might read a stale value, since on modern architectures you have multiple cores with individual cache that is not kept in sync automatically. You need a read memory barrier, usually a platform-specific instruction.

    On Wintel, thread synchronization functions will automatically add a full memory barrier, or you can use the InterlockedXxxx functions.

    MSDN: Memory and Synchronization issues, MemoryBarrier Macro

    [edit] please also see drhirsch's comments.

    0 讨论(0)
  • 2020-12-02 09:16

    This may happen on 8 bit systems which use 16 bit integers.

    If you want to avoid locking you can under suitable circumstances get away with reading multiple times, until you get two equal consecutive values. For example, I've used this approach to read the 64 bit clock on a 32 bit embedded target, where the clock tick was implemented as an interrupt routine. In that case reading three times suffices, because the clock can only tick once in the short time the reading routine runs.

    0 讨论(0)
  • 2020-12-02 09:16

    In general, each machine instruction goes thru several hardware stages when executing. As most current CPUs are multi-core or hyper-threaded, that means that reading a variable may start it moving thru the instruction pipeline, but it doesn't stop another CPU core or hyper-thread from concurrently executing a store instruction to the same address. The two concurrently executing instructions, read and store, might "cross paths", meaning that the read will receive the old value just before the new value is stored.
    To resume: you do need the mutex for both read and writes.

    0 讨论(0)
  • 2020-12-02 09:18

    I'd recommend not to rely on any compiler or architecture in this case.
    Whenever you have a mix of readers and writers (as opposed to just readers or just writers) you'd better sync them all. Imagine your code running an artificial heart of someone, you don't really want it to read wrong values, and surely you don't want a power plant in your city go 'boooom' because someone decided not to use that mutex. Save yourself a night-sleep in a long run, sync 'em.
    If you only have one thread reading -- you're good to go with just that one mutex, however if you're planning for multiple readers and multiple writers you'd need a sophisticated piece of code to sync that. A nice implementation of read/write lock that would also be 'fair' is yet to be seen by me.

    0 讨论(0)
  • 2020-12-02 09:21

    Both reading / writing to variables with concurrency must be protected by a critical section (not mutex). Unless you want to waste your whole day debugging.

    Critical sections are platform-specific, I believe. On Win32, critical section is very efficient: when no interlocking occur, entering critical section is almost free and does not affect overall performance. When interlocking occur, it is still more efficient, than mutex, because it implements a series of checks before suspending the thread.

    0 讨论(0)
  • 2020-12-02 09:23

    Depends on your platform. Most modern platforms offer atomic operations for integers: Windows has InterlockedIncrement, InterlockedDecrement, InterlockedCompareExchange, etc. These operations are usually supported by the underlying hardware (read: the CPU) and they are usually cheaper than using a critical section or other synchronization mechanisms.

    See MSDN: InterlockedCompareExchange

    I believe Linux (and modern Unix variants) support similar operations in the pthreads package but I don't claim to be an expert there.

    0 讨论(0)
提交回复
热议问题