简体   繁体   中英

should I use a lock if I am sure that every thread will always write the same value to shared memory?

C++: I have a vector<bool> , no thread will ever write false to any of the indices. Should I still use a lock? I don't think it will cause a race condition as all threads are writing the same value. The functions being accessed by multiple threads looks like:

void setVal(int index) 
{
  if (boolvec[index] == false)
    boolvec[index] = true; 
}

To get by without a lock you should use a std::vector<atomic_flag_wrapper> where atomic_flag_wrapper wraps a std::atomic_flag similar to the code in this answer .

With std::vector<bool> you must use a lock , the standard explicitly tells you so:

Notwithstanding [res.on.data.races], implementations are required to avoid data races when the contents of the contained object in different elements in the same container, excepting vector<bool> , are modified concurrently.

http://eel.is/c++draft/container.requirements.dataraces#2 (C++ draft, 02.08.2020), emphasis mine

In plain English:

std::vector<bool> does not need to make sure that writes to two different elements are race-free; therefore there can be a data race; therefore you need a lock.

If it were eg a std::vector<char> , then the standard makes sure that charVector[0] and charVector[1] can be written to concurrently. But still then you cannot write to charVector[0] from more than one thread concurrently; you need to use atomics .

std:atomic<bool> is not guaranteed to be lock-free, so you should use std::atomic_flag which has this guarantee. You cannot put these into a std::vector , though, because they are not copy constructible. For that, you need a wrapper as described in this answer .

You should use a lock. On some platforms it may be unnecessary, while on others it is essential to get correct functionality due to the nature of std::vector<bool> .

std::vector<bool> is designed for space efficiency, and elements are stored on individual bits. If one thread writes to boolvec[3] , and another writes to boolvec[4] , both will modify the same byte in memory. This requires a lock to ensure that the proper value is visible to all threads because of the read-modify-write cycle necessary to change the value. Without the lock, one some platforms the first write may not be immediately visible to all CPUs/cores/threads, resulting in the second write using a stale value, effectively undoing the previous thread's write to the same address.

Yes, you should. Always a good idea, since it affects readability and maintainability. Even though in the current day your code may not be expected to write specific values, in the future, that may change. While it may work currently without a lock, suppose you want to change something. Then you get a bug and have to chase it down--a bug you could have reasonably prevented by writing your code defensively from the beginning.

In this specific case you can avoid using lock. In case multiple threads read false at the same index it does not matter, since the end result will be that value at that index is true.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM