Is using unique_lock in new scope equivalent to unlock call at the end of work with shared resource?

std::unique_lock
lock_guard recursive_mutex
unique_lock vs scoped_lock
unique_lock condition_variable
std::lock_guard
std::mutex
unique_lock vs lock_guard
unique_lock vs shared_lock

I have seen a lot of examples of code when developer uses std::unique_lock in new scope for automatically unlocking mutex:

...
// do some staff
{
  std::unique_lock<std::mutex> lock(shared_resource_mutex);
  // do some actions with shared resource
}
// do some staff
...

In my opinion it would be better to implement this behaviour using method unlock from std::unique_lock API in this way:

...
// do some actions
std::unique_lock<std::mutex> lock(shared_resource_mutex);
// do some actions with shared resource
lock.unlock();
// do some actions
...

Are these two fragments of code equivalent? For what purpose developers use the first variant? Maybe to emphasize (using parentheses) code that can not be executed parallel?


I would say the former method is safer, more consistent and easier to read.

First consider safety:

void function()
{
    std::unique_lock<std::shared_mutex> lock(mtx);

    // exclusive lock stuff

    lock.unlock();

//  std::shared_lock<std::shared_mutex> lock(mtx); // whoops name in use
    std::shared_lock<std::shared_mutex> lock2(mtx);

    // read only shared lock stuff here

    lock2.unlock(); // what if I forget to do this?

    lock.lock(); // if I forgot to call lock2.unlock() undefined behavior

    // back to the exclusive stuff

    lock.unlock();  
}

If you have different locks to acquire/release and you forget to call unlock() then you may end up trying to lock the same mutex twice from the same thread.

That is undefined behavior so it may go unnoticed but cause trouble.

And what if you call either lock() or unlock() on the wrong lock variable.... (say on lock2 rather than lock1?) the possibilities are frightening.

Consistency:

Also, not all lock types have a .unlock() function (std::scoped_lock, std::lock_guard) so it is good to be consistent with your coding style.

Easier to read:

It is also easier to see what code sections use locks which makes reasoning on the code simpler:

void function()
{
    {
        std::unique_lock<std::shared_mutex> lock(mtx);

        // exclusive lock stuff
    }

    {
        std::shared_lock<std::shared_mutex> lock(mtx);

        // read only shared lock stuff here
    }

    {
        std::unique_lock<std::shared_mutex> lock(mtx);

        // back to the exclusive stuff
    }
}

unique_lock - C++ Reference, can be created without immediately locking, can unlock at any point in its existence, and can transfer ownership of the lock from one instance to another. pthread_mutex_destroy, pthread_mutex_init - destroy and initialize a. mutex. SYNOPSIS. #include <pthread.h> int pthread_mutex_destroy(pthread_mutex_t *mutex);


When the object is destroyed at the end of the scope, the lock is released. That's the whole point of RAII.

The good thing about using RAII is that you cannot forget to unlock and it doesn't matter how you leave the scope. If an exception is thrown for example, the lock will still be released.

If all you need is lock at construction and unlock at destruction, then std::scoped_lock is an even simpler/more appropriate class to use though.

std::unique_lock<std::mutex> or std::lock_guard , is a general-purpose mutex ownership wrapper allowing deferred locking, time-constrained attempts at locking, recursive locking, transfer of lock ownership, and use with condition variables. The scoped_lock is meant to address the most common use case, which is also the simplest use case: Lock the mutex at the beginning of a scope and unlock it at the end of the scope. That mutex could be a mutex, or a recursive_timed_mutex, or a MySpecialMutex. scoped_lock does not care.


Both of your approaches are correct, and you might choose either of them depending on circumstance. For example, when using a condition_variable/lock combination it's often useful to be able to explicitly lock and unlock the lock.

Here's another approach that I find to be both expressive and safe:

#include <mutex>

template<class Mutex, class Function>
decltype(auto) with_lock(Mutex& m, Function&& f)
{
    std::lock_guard<Mutex> lock(m);
    return f();
}

std::mutex shared_resource_mutex;

void something()
{
    with_lock(shared_resource_mutex, [&]
    {
        // some actions
    });

    // some other actions
}

std::unique_lock - cppreference.com, is constructed it will lock the mutex, and it gets destructed it will unlock the mutex. The concurrency::reader_writer_lock class provides thread-safe read/write operations to shared data. Use reader/writer locks when multiple threads require concurrent read access to a shared resource but rarely write to that shared resource. This class gives only one thread write access to an object at any time.


How to use/create unique_lock in c++?, One way of preventing data races between the threads is to use But when we synchronized threads with a condition variable, we used similar class: std::​unique_lock . At the end of guard1 's life, the destructor unlocks the mutex. First part of the function accesses some shared resource and the second  Applications using Thread::Apartment to support zone threading (i.e., multiple objects installed in a single apartment thread) may need to implement extra locking functionality if the objects within the thread are sharing the same resource in read and write modes, as Thread::Resource::RWLock relies on the current TID (via threads::tid()) to


Difference between std::lock_guard and std::unique_lock, The thread asks for unique ownership of the shared data protected by the a new value using rawQueue.push() : it adds a new element at the end of to call unlock() or, when possible, use std::lock_guard (or similar) It always guarantees to unlock the mutex using the RAII (Resource lg exits its scope. Thanks for the question, Gururaj. Asked: June 21, 2001 - 9:52 am UTC. Answered by: Tom Kyte - Last updated: October 24, 2017 - 2:13 am UTC


[C++] MUTEX: Write Your First Concurrent Code, Locks take care of thier resource following the RAII idiom. A std::unique_lock enables youin addition to std::lock_guard void deadLock(CriticalData& a, CriticalData& b){ a.mut.lock(); std::cout << "get the first mutex" It waits in line 21 by using the call t.join(), until its child t is done with its work package. Microsoft Access Forum By Richard Rost Welcome to the Microsoft Access Forum.Access is by far our most popular topic here at Computer Learning Zone. This forum is for everyone to read but only students (paid customers) can post here.