atari83
atari83

Reputation: 489

clarification on using std::unique_lock

So, I have a std::map object which is getting accessed by multiple threads in same time and I decided to use unique_lock to make the map operation safe.

In one of thread's implementation, the map object is getting used by some functions (these functions generally add/remove items from map object), So I wanted to know if defining the unique_lock at the top of parent function would be guarantee the safety ? or i need to add it to every single of those functions ?

void Thread1() {
  std::unique_lock<std::mutex> ul(mutex);

  func1();  // map object is getting changed here
  func2();  // map object is getting changed here

}

Upvotes: 0

Views: 631

Answers (2)

Solomon Slow
Solomon Slow

Reputation: 27210

The whole point of using the mutex is to prevent threads B, C, D, etc. from seeing shared data in an inconsistent state because of changes made by thread A.

You proposed this:

void Thread1() {
    std::unique_lock<std::mutex> ul(mutex);
    func1();  // map object is getting changed here
    func2();  // map object is getting changed here
}

Does func1() leave the map (and maybe other shared variables) in a state that other threads should not see? and does func2() make it OK again for other threads to see the shared data? If so, then your example probably is the best you can hope for. But, if each of those two function calls leaves the shared data in a "safe" state, then you might consider having each one of them separately lock and unlock the mutex.

You're usually better off if threads can be designed so that they don't often need to access shared data, and when they do need to access it, they get in and out (i.e., lock and unlock) as quickly as possible.


See also, readers writer locking (in C++, std::shared_lock) in case that happens to help with your particular problem.

Upvotes: 1

West
West

Reputation: 742

What I see you have here can't really work. If every thread tries to grab the mutex at the start of operation either you have deadlock or sequential threads where only one thread can run or you have multiple different mutexes. The latter is not correct but the former kind of gives up some of the benefits of multithreading.

If you used more explicit scoping for the functions that have to be locked that it is fine to use locks without adding them directly to functions in use.

void Thread1() {
funcA();
{// Explicit scoping
std::unique_lock<std::mutex> ul(mutex);

func1();  // map object is getting changed here
func2();  // map object is getting changed here
}
funcB();

}

We want to use locks for the smallest period possible. So you have to make a judgment call on whether the functions that change the map object are small enough to justify locking for the entire time.

Upvotes: 1

Related Questions