Do I need to use locking with integers in c++ threads

前端 未结 7 1465
慢半拍i
慢半拍i 2021-01-04 21:10

If I am accessing a single integer type (e.g. long, int, bool, etc...) in multiple threads, do I need to use a synchronisation mechanism such as a mutex to lock them. My un

相关标签:
7条回答
  • 2021-01-04 21:13

    Multithreading is hard and complex. The number of hard to diagnose problems that can come around is quite big. In particular, on intel architectures reads and writes from aligned 32bit integers is guaranteed to be atomic in the processor, but that does not mean that it is safe to do so in multithreaded environments.

    Without proper guards, the compiler and/or the processor can reorder the instructions in your block of code. It can cache variables in registers and they will not be visible in other threads...

    Locking is expensive, and there are different implementations of lock-less data structures to optimize for high performance, but it is hard to do it correctly. And the problem is a that concurrency bugs are usually obscure and difficult to debug.

    0 讨论(0)
  • 2021-01-04 21:20

    Yes. If you are on Windows you can take a look at Interlocked functions/variables and if you are of the Boost persuasion then you can look at their implementation of atomic variables.

    If boost is too heavyweight putting "atomic c++" into your favourite search engine will give you plenty of food for thought.

    0 讨论(0)
  • 2021-01-04 21:31

    In 99.99% of the cases, you must lock, even if it's access to seemingly atomic variables. Since C++ compiler is not aware of multi-threading on the language level, it can do a lot of non-trivial reorderings.

    Case in point: I was bitten by a spin lock implementation where unlock is simply assigning zero to a volatile integer variable. The compiler was reordering unlock operation before the actual operation under the lock, unsurprisingly, leading to mysterious crashes.

    See:

    1. Lock-Free Code: A False Sense of Security
    2. Threads Cannot be Implemented as a Library
    0 讨论(0)
  • 2021-01-04 21:32

    If you're on a machine with more than one core, you need to do things properly even though writes of an integer are atomic. The issues are two-fold:

    1. You need to stop the compiler from optimizing out the actual write! (Somewhat important this. ;-))
    2. You need memory barriers (not things modeled in C) to make sure the other cores take notice of the fact that you've changed things. Otherwise you'll be tangled up in caches between all the processors and other dirty details like that.

    If it was just the first thing, you'd be OK with marking the variable volatile, but the second is really the killer and you will only really see the difference on a multicore machine. Which happens to be an architecture that is becoming far more common than it used to be… Oops! Time to stop being sloppy; use the correct mutex (or synchronization or whatever) code for your platform and all the details of how to make memory work like you believe it to will go away.

    0 讨论(0)
  • 2021-01-04 21:32

    Yes it would be better to use synchronization. Any data accessed by multiple threads must be synchronized.

    If it is windows platform you can also check here :Interlocked Variable Access.

    0 讨论(0)
  • 2021-01-04 21:35

    You are never locking a value - you are locking an operation ON a value.

    C & C++ do not explicitly mention threads or atomic operations - so operations that look like they could or should be atomic - are not guaranteed by the language specification to be atomic.

    It would admittedly be a pretty deviant compiler that managed a non atomic read on an int: If you have an operation that reads a value - theres probably no need to guard it. However- it might be non atomic if it spans a machine word boundary.

    Operations as simple as m_counter++ involves a fetch, increment, and store operation - a race condition: another thread can change the value after the fetch but before the store - and hence needs to be protected by a mutex - OR find your compilers support for interlocked operations. MSVC has functions like _InterlockedIncrement() that will safely increment a memory location as long as all other writes are similarly using interlocked apis to update the memory location - which is orders of magnitude more lightweight than invoking a even a critical section.

    GCC has intrinsic functions like __sync_add_and_fetch which also can be used to perform interlocked operations on machine word values.

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