spooja__
spooja__

Reputation: 223

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; 
}

Upvotes: 3

Views: 280

Answers (4)

Daniel Jour
Daniel Jour

Reputation: 16156

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 e.g. 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.

Upvotes: 5

1201ProgramAlarm
1201ProgramAlarm

Reputation: 32732

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.

Upvotes: 3

C. Ventin
C. Ventin

Reputation: 135

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.

Upvotes: 1

magikarp
magikarp

Reputation: 129

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.

Upvotes: -2

Related Questions