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.