精华内容
下载资源
问答
  • error: use of deleted function ‘std::mutex::mutex(const std::mutex&)
    2022-03-07 15:57:32

    当std:mutex作为类的成员的时候,例如:

    class Object {
    private:
        std::mutex mutex_;
    }

    cmake编译核心报错:

    error: use of deleted function ‘std::mutex::mutex(const std::mutex&)

    查了查mutex构造函数:

        mutex(const mutex&) = delete;
        mutex& operator=(const mutex&) = delete;

     这是显示地告诉编译器删除编译器默认生成的拷贝构造和移动构造函数,所以mutex对象不能进行拷贝构造和移动构造。

    但是在类中并没有"明显"进行拷贝构造和移动拷贝

    试着将std::mutex定义为全局变量,编译通过:

    std::mutex g_mutex;
    
    class Object {
    public:
        lock() {
            std::unique_lock<std::mutex>lock(g_mutex);
        }
    }

    又试了试这样,编译通过:

    class Object {
    public:
        Object() {
            mutex_ = new std::mutex();
        }
        lock() {
            std::unique_lock<std::mutex>lock(*mutex_);
        }
        ~Objext() {
            delete mutex_;
        }
    private:
        std::mutex* mutex_;
    }

    但是没有找到相关的类类型的类成员内部是如何初始化的,也许可能是先在栈上构造了一个临时对象吧,然后用了移动语义初始化成员mutex_造成的。

    更多相关内容
  • 上一篇《C++11 并发指南二(std::thread 详解) 》中主要讲到了 std::thread 的一些用法,并给出了两个小例子,本文将介绍 std::mutex 的用法。 Mutex 又称互斥量,C++ 11中与 Mutex 相关的类(包括锁类型)和函数都...
  • It can be used when you need a wrapper for a limited scope, eg: a member function: 当需要有限范围的包装器时可以使用它,例如:成员函数: class MyClass{ std::mutex my_mutex; void member_foo() { std::...

    本文翻译自:std::unique_lock or std::lock_guard?

    I have two use cases. 我有两个用例。

    A. I want to synchronise access by two threads to a queue. 答:我想通过两个线程同步对队列的访问。

    B. I want to synchronise access by two threads to a queue and use a condition variable because one of the threads will wait on content to be stored into the queue by the other thread. B.我想同步两个线程对队列的访问并使用条件变量,因为其中一个线程将等待内容被另一个线程存储到队列中。

    For use case AI see code example using std::lock_guard<> . 对于用例AI,请参见使用std::lock_guard<>代码示例。 For use case BI see code example using std::unique_lock<> . 对于用例BI,请参见使用std::unique_lock<>代码示例。

    What is the difference between the two and which one should I use in which use case? 两者之间有什么区别?在哪种用例中应该使用哪一种?


    #1楼

    参考:https://stackoom.com/question/1O5Lh/std-unique-lock-std-mutex-或std-lock-guard-std-mutex


    #2楼

    Use lock_guard unless you need to be able to manually unlock the mutex in between without destroying the lock . 除非需要能够在不破坏lock情况下手动unlock互斥锁,否则请使用lock_guard

    In particular, condition_variable unlocks its mutex when going to sleep upon calls to wait . 特别是, condition_variable在调用wait进入睡眠状态时会解锁其互斥量。 That is why a lock_guard is not sufficient here. 这就是为什么lock_guard在这里不够的原因。


    #3楼

    The difference is that you can lock and unlock a std::unique_lock . 区别在于您可以锁定和解锁std::unique_lock std::lock_guard will be locked only once on construction and unlocked on destruction. std::lock_guard在构造时将仅被锁定一次,在破坏时将被解锁。

    So for use case B you definitely need a std::unique_lock for the condition variable. 因此,对于用例B,您肯定需要一个std::unique_lock作为条件变量。 In case A it depends whether you need to relock the guard. 如果是A,则取决于是否需要重新锁定防护装置。

    std::unique_lock has other features that allow it to eg: be constructed without locking the mutex immediately but to build the RAII wrapper (see here ). std::unique_lock具有其他功能,例如,可以在不立即锁定互斥体的情况下构造它,但可以构建RAII包装器(请参见此处 )。

    std::lock_guard also provides a convenient RAII wrapper, but cannot lock multiple mutexes safely. std::lock_guard还提供了方便的RAII包装器,但不能安全地锁定多个互斥体。 It can be used when you need a wrapper for a limited scope, eg: a member function: 当需要有限范围的包装器时可以使用它,例如:成员函数:

    class MyClass{
        std::mutex my_mutex;
        void member_foo() {
            std::lock_guard<mutex_type> lock(this->my_mutex);            
            /*
             block of code which needs mutual exclusion (e.g. open the same 
             file in multiple threads).
            */
    
            //mutex is automatically released when lock goes out of scope           
    };
    

    To clarify a question by chmike, by default std::lock_guard and std::unique_lock are the same. 为了通过chmike澄清问题,默认情况下std::lock_guardstd::unique_lock相同。 So in the above case, you could replace std::lock_guard with std::unique_lock . 因此,在上述情况下,您可以将std::lock_guard替换为std::unique_lock However, std::unique_lock might have a tad more overhead. 但是, std::unique_lock可能会有更多开销。

    Note that these days one should use std::scoped_lock instead of std::lock_guard . 请注意,这些天应该使用std::scoped_lock而不是std::lock_guard


    #4楼

    lock_guard and unique_lock are pretty much the same thing; lock_guardunique_lock几乎是同一件事; lock_guard is a restricted version with a limited interface. lock_guard是具有受限接口的受限版本。

    A lock_guard always holds a lock from its construction to its destruction. 从构造到破坏, lock_guard始终保持着锁。 A unique_lock 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. 可以在不立即锁定的情况下创建unique_lock ,可以在其存在的任何时候将其解锁,并且可以将锁的所有权从一个实例转移到另一个实例。

    So you always use lock_guard , unless you need the capabilities of unique_lock . 因此,除非需要unique_lock的功能,否则始终使用lock_guard A condition_variable needs a unique_lock . condition_variable需要unique_lock


    #5楼

    As has been mentioned by others, std::unique_lock tracks the locked status of the mutex, so you can defer locking until after construction of the lock, and unlock before destruction of the lock. 正如其他人提到的那样,std :: unique_lock跟踪互斥锁的锁定状态,因此您可以将锁定推迟到构造锁之后,再解锁直到销毁锁为止。 std::lock_guard does not permit this. std :: lock_guard不允许这样做。

    There seems no reason why the std::condition_variable wait functions should not take a lock_guard as well as a unique_lock, because whenever a wait ends (for whatever reason) the mutex is automatically reacquired so that would not cause any semantic violation. 似乎没有理由为什么std :: condition_variable等待函数不应该同时使用lock_guard和unique_lock,因为只要等待结束(无论出于何种原因),都会自动重新获取互斥体,因此不会引起任何语义冲突。 However according to the standard, to use a std::lock_guard with a condition variable you have to use a std::condition_variable_any instead of std::condition_variable. 但是,根据标准,要将std :: lock_guard与条件变量一起使用,则必须使用std :: condition_variable_any而不是std :: condition_variable。

    Edit : deleted "Using the pthreads interface std::condition_variable and std::condition_variable_any should be identical". 编辑 :删除了“使用pthreads接口std :: condition_variable和std :: condition_variable_any应该相同”。 On looking at gcc's implementation: 在查看gcc的实现时:

    • std::condition_variable::wait(std::unique_lock&) just calls pthread_cond_wait() on the underlying pthread condition variable with respect to the mutex held by unique_lock (and so could equally do the same for lock_guard, but doesn't because the standard doesn't provide for that) std :: condition_variable :: wait(std :: unique_lock&)只是针对与unique_lock持有的互斥锁在底层pthread条件变量上调用pthread_cond_wait()(因此,对lock_guard可以同样执行此操作,但不是因为标准没有为此提供)
    • std::condition_variable_any can work with any lockable object, including one which is not a mutex lock at all (it could therefore even work with an inter-process semaphore) std :: condition_variable_any可以与任何可锁定对象一起使用,包括根本不是互斥锁的对象(因此甚至可以与进程间信号灯一起使用)

    #6楼

    There are certain common things between lock_guard and unique_lock and certain differences. lock_guardunique_lock之间有某些共同之处,也有一些区别。

    But in the context of the question asked, the compiler does not allow using a lock_guard in combination with a condition variable, because when a thread calls wait on a condition variable, the mutex gets unlocked automatically and when other thread/threads notify and the current thread is invoked (comes out of wait), the lock is re-acquired. 但是在提出问题的上下文中,编译器不允许将lock_guard与条件变量结合使用,因为当线程调用等待条件变量时,互斥锁会自动解锁,而其他线程/线程通知当前线程被调用(退出等待状态),重新获得该锁。

    This phenomenon is against the principle of lock_guard . 这种现象违反了lock_guard的原理。 lock_guard can be constructed only once and destructed only once. lock_guard只能构造一次,并且只能破坏一次。

    Hence lock_guard cannot be used in combination with a condition variable, but a unique_lock can be (because unique_lock can be locked and unlocked several times). 因此lock_guard不能与条件变量组合使用,但一个unique_lock即可(因为unique_lock可以被锁定和解锁几次)。

    展开全文
  • std::mutex:最基本的mutex类。 std::recursive_mutex:递归mutex类,能多次锁定而不死锁。 std::time_mutex:定时mutex类,可以锁定一定的时间。 std::recursive_timed_mutex:定时递归mutex类。 另外,还提供...

    C++11中提供了std::mutex互斥量,共包含四种类型:

        std::mutex:最基本的mutex类。
        std::recursive_mutex:递归mutex类,能多次锁定而不死锁。
        std::time_mutex:定时mutex类,可以锁定一定的时间。
        std::recursive_timed_mutex:定时递归mutex类。

    另外,还提供了两种锁类型:

        std::lock_guard:方便线程对互斥量上锁。

        std::unique_lock:方便线程对互斥量上锁,但提供了更好的上锁和解锁控制。

        以及相关的函数:
        std::try_lock:尝试同时对多个互斥量上锁。
        std::lock:可以同时对多个互斥量上锁。
        std::call_once:如果多个线程需要同时调用某个函数,call_once可以保证多个线程对该函数只调用一次。

    std::mutex

    std::mutex是C++中最基本的互斥量,提供了独占所有权的特性,std::mutex提供了以下成员函数

        构造函数:std::mutex不允许拷贝构造,也不允许move拷贝,最初产生的mutex对象是处于unlocked状态的。
        lock():调用线程将锁住该互斥量,线程调用该函数会发生以下3种情况:
        (1)如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用unlock之前,该线程一直拥有该锁。
        (2)如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住。
        (3)如果当前互斥量被当前调用线程锁住,则会产生死锁,,也就是说同一个线程中不允许锁两次。
        unlock():解锁,释放对互斥量的所有权。
        try_lock():尝试锁住互斥量,如果互斥量被其他线程占有,则当前线程也不会被阻塞,线程调用该函数会出现下面3种情况:
        (1)如果当前互斥量没有被其他线程占有,则该线程锁住互斥量,直到该线程调用unlock释放互斥量。
        (2)如果当前互斥量被其他线程锁住,则当前调用线程返回false,而并不会被阻塞掉。
        (3)如果当前互斥量被当前调用线程锁住,则会产生死锁。

    int counter = 0;
    std::mutex mtx;
    
    void func() {
        for (int i = 0; i < 10000; ++i)
        {
            mtx.lock();
            ++counter;
            mtx.unlock();
        }
    }
    
    int main()
    {
        std::thread threads[10];
    
        for (int i = 0; i < 10; ++i)
        {
            threads[i] = std::thread(func);
        }
    
        for (auto& th : threads)
        {
            th.join();
        }
        std::cout << counter << std::endl;   // 100000
    
        return 0;
    }
    
        

    以上代码实现了对counter的同步操作,同时只有一个线程能对counter操作。我们再看一下try_lock的结果:

    void func() {
        for (int i = 0; i < 10000; ++i)
        {
            if (mtx.try_lock())
            {
                ++counter;
                mtx.unlock();
            }
        }
    }
    
    int main()
    {
        std::thread threads[10];
    
        for (int i = 0; i < 10; ++i)
        {
            threads[i] = std::thread(func);
        }
    
        for (auto& th : threads)
        {
            th.join();
        }
        std::cout << counter << std::endl;   // 不固定
    
        return 0;
    }
    
        

    可以看到,使用try_lock对counter进行控制,最终结果是不固定的。因为try_lock在其他线程占有互斥量的情况下会返回false但是不阻塞,所以会跳过一部分的++counter操作。

    std::recursive_mutex

    std::recursive_mutex与std::mutex类似,但是它能够进行多次lock,这样能够规避一些死锁问题:

    int counter = 0;
    std::recursive_mutex mtx;
    
    void func2() {
        mtx.lock();
        counter++;
        mtx.unlock();
    }
    
    void func1() {
        mtx.lock();
        func2();
        counter++;
        mtx.unlock();
    }
    
    int main()
    {
        std::thread t(func1);
    
        t.join();
        std::cout << counter << std::endl;   // 2
    
        return 0;
    }

    如上面的代码所示,有时候会在两个函数中分别对数据进行lock,如果在一个函数中又调用了另一个函数,此时如果使用std::mutex将会死锁,而用std::recursive_mutex则不会。看起来std::recursive_mutex很不错,但是使用的时候也需要多注意,lock和unlock的数量必须相等,否则会出错。

    另外还有性能的问题,std::recursive_mutex的性能会比较差一些,从下面的例子中可以看出来,性能上要差了1倍左右。

    int counter = 0;
    std::recursive_mutex rmtx;
    std::mutex mtx;
    
    
    int main()
    {
        auto begin = std::chrono::system_clock::now();
        for (int i = 0; i < 10000; ++i)
        {
            mtx.lock();
            counter++;
            mtx.unlock();
        }
        auto end = std::chrono::system_clock::now();
        std::cout << (end - begin).count() << std::endl;  // 330
    
        begin = std::chrono::system_clock::now();
        for (int i = 0; i < 10000; ++i)
        {
            rmtx.lock();
            counter++;
            rmtx.unlock();
        }
        end = std::chrono::system_clock::now();         
        std::cout << (end - begin).count() << std::endl; // 597
    
        return 0;
    }

        std::time_mutex和std::recursive_timed_mutex

    这两种互斥量类型和不带time的相比,多了两个成员函数:

        try_lock_for():函数参数表示一个时间范围,在这一段时间范围之内线程如果没有获得锁则保持阻塞;如果在此期间其他线程释放了锁,则该线程可获得该互斥锁;如果超时(指定时间范围内没有获得锁),则函数调用返回false。
        try_lock_until():函数参数表示一个时刻,在这一时刻之前线程如果没有获得锁则保持阻塞;如果在此时刻前其他线程释放了锁,则该线程可获得该互斥锁;如果超过指定时刻没有获得锁,则函数调用返回false。

    首先来看看try_lock_for的用法,下面的例子可以看出,try_lock_for等待指定时间后没有获取到锁,会返回false。

    #include <iostream>       // std::cout
    #include <chrono>         // std::chrono::milliseconds
    #include <thread>         // std::thread
    #include <mutex>          // std::timed_mutex
    
    std::timed_mutex mtx;
    
    void fireworks(int n) {
        // 为这个锁等待200ms
        while (!mtx.try_lock_for(std::chrono::milliseconds(200))) {
            std::string out = std::to_string(n);
            out += "wait\n";
            std::cout << out;
        }
    
        // 获取锁后等待700ms再解锁
        std::this_thread::sleep_for(std::chrono::milliseconds(700));
        std::cout << "end" << std::endl;
        mtx.unlock();
    }
    
    int main ()
    {
        std::thread threads[3];
        for (int i = 0; i < 3; ++i)
        {
           threads[i] = std::thread(fireworks, i);
           // 为了保证线程按照顺序开始,保证输出一致
           std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    
        for (auto& th : threads)
        {
           th.join();
        }
    
        return 0;
    }
    
    // 输出结果
    1wait
    2wait
    1wait
    2wait
    1wait
    2wait
    end
    2wait
    2wait
    2wait
    end
    end

       try_lock_until的作用类似,不同的是传入参数是时间点:

    void fireworks(int n) {
        auto now  = std::chrono::steady_clock::now();
        while (!mtx.try_lock_until(now +  std::chrono::milliseconds(200))) {
            std::string out = std::to_string(n);
            out += "wait\n";
            std::cout << out;
            now  = std::chrono::steady_clock::now();
        }
    
        std::this_thread::sleep_for(std::chrono::milliseconds(700));
        std::cout << "end" << std::endl;
        mtx.unlock();
    }

     std::recursive_timed_mutex和std::recursive_mutex的区别也是一样的,多了两个成员函数。

    std::lock_guard和std::unique_lock

    std::lock_guard是一个模板类,模板类型可以是以上的四种锁,用于自动锁定解锁,直到对象作用域结束。

    std::mutex mtx;
    
    int main ()
    {
        {
            std::lock_guard<std::mutex> guard(mtx);
            std::cout << mtx.try_lock() << std::endl;  // 0,互斥量被占用
        }
    
        std::cout << mtx.try_lock() << std::endl;     // 0,互斥量释放
        mtx.unlock();
    
        return 0;
    }

      std::unique_lock也支持std::lock_guard的功能,但是区别在于它提供跟多的成员函数使用更加灵活,并且能够和condition_variable一起使用来控制线程同步,内容较多以后有机会在做介绍,有兴趣的朋友可以自己了解。

    std::try_lock、std::lock、std::call_once

    std::try_lock支持尝试对多个互斥量进行锁定,尝试锁定成功返回-1,否则返回锁定失败的互斥量的位置,例如第一个锁定失败返回0、第二个失败返回1。

    int main ()
    {
        std::mutex mtx1;
        std::mutex mtx2;
    
        if (-1 == std::try_lock(mtx1, mtx2))
        {
            std::cout << "locked" << std::endl;
            mtx1.unlock();
            mtx2.unlock();
        }
    
        return 0;
    }

       std::lock支持对多个锁锁定,并且避免死锁的出现,以下代码运行时有可能出现死锁的情况:

    void func(std::mutex* mtx1, std::mutex* mtx2, int index)
    {
        std::lock_guard<std::mutex> lock1(std::adopt_lock);
        std::lock_guard<std::mutex> lock2(std::adopt_lock);
    
        std::cout << index << "out\n";
    }
    
    int main ()
    {
        std::mutex mtx1;
        std::mutex mtx2;
    
        // 两个线程的互斥量锁定顺序不同,可能造成死锁
        std::thread t1(func, &mtx1, &mtx2, 1);
        std::thread t2(func, &mtx2, &mtx1, 2);
    
        t1.join();
        t2.join();
    
        return 0;
    }

    而用std::lock能避免多个锁出现死锁:

    void func(std::mutex* mtx1, std::mutex* mtx2, int index)
    {
        std::lock(*mtx1, *mtx2); // 同时锁定
    
        // std::adopt_lock作用是声明互斥量已在本线程锁定,std::lock_guard只是保证互斥量在作用域结束时被释放
        std::lock_guard<std::mutex> lock1(*mtx1, std::adopt_lock);
        std::lock_guard<std::mutex> lock2(*mtx2, std::adopt_lock);
    
        // 等价方法:
        //std::unique_lock<std::mutex> lock1(from.m, std::defer_lock);
        //std::unique_lock<std::mutex> lock2(to.m, std::defer_lock);
        //std::lock(lock1, lock2);
    
        std::cout << index << "out\n";
    }
    
    int main ()
    {
        std::mutex mtx1;
        std::mutex mtx2;
    
        std::thread t1(func, &mtx1, &mtx2, 1);
        std::thread t2(func, &mtx2, &mtx1, 2);
    
        t1.join();
        t2.join();
    
        return 0;
    }

    std::call_once的作用是即使在多线程的情况下,也只执行一次指定的可调用对象(可以是函数、成员函数、函数对象、lambda函数),需要通过配合std::once_flag实现。具体的细节如下:

        若在调用 call_once 的时刻, flag 指示已经调用了f指定的可调用对象,则 call_once 立即返回,就是说不再执行可调用对象。
        否则,call_once 会调用指定的可调用对象。若该调用对象抛异常,则传播异常给 call_once 的调用方,并且不翻转 flag ,让下一次调用仍然执行。若该调用正常返回,则翻转 flag ,并保证同一 flag不在执行可调用对象。

    std::once_flag flag1, flag2;
    
    void simple_do_once()
    {
        std::call_once(flag1, [](){ std::cout << "Simple example: called once\n"; });
    }
    
    void may_throw_function(bool do_throw)
    {
        if (do_throw) {
            std::cout << "throw: call_once will retry\n"; // this may appear more than once
            throw std::exception();
        }
        std::cout << "Didn't throw, call_once will not attempt again\n"; // guaranteed once
    }
    
    void do_once(bool do_throw)
    {
        try {
            std::call_once(flag2, may_throw_function, do_throw);
        }
        catch (...) {
        }
    }
    
    int main()
    {
        std::thread st1(simple_do_once);
        std::thread st2(simple_do_once);
        std::thread st3(simple_do_once);
        std::thread st4(simple_do_once);
        st1.join();
        st2.join();
        st3.join();
        st4.join();
    
        std::thread t1(do_once, true);
        std::thread t2(do_once, true);
        std::thread t3(do_once, false);
        std::thread t4(do_once, true);
        t1.join();
        t2.join();
        t3.join();
        t4.join();
    }
    
    // 输出结果:
    Simple example: called once
    throw: call_once will retry
    throw: call_once will retry
    Didn't throw, call_once will not attempt again

    https://blog.csdn.net/WizardtoH/article/details/81452066

    展开全文
  • std::mutex::lock

    千次阅读 2020-02-23 12:00:53
    std::mutex::lock Defined in header <mutex> - 定义于头文件 <mutex> public member function - 公开成员函数 锁定互斥,若互斥不可用则阻塞。 mutex:n. 互斥,互斥元,互斥体,互斥量 ...

    std::mutex::lock

    Defined in header <mutex> - 定义于头文件 <mutex>

    public member function - 公开成员函数

    锁定互斥,若互斥不可用则阻塞。

    mutex:n. 互斥,互斥元,互斥体,互斥量
    synchronization [ˌsɪŋkrənaɪˈzeɪʃn]:n. 同步,同时性
    primitive [ˈprɪmətɪv]:adj. 原始的,远古的,简单的,粗糙的 n. 原始人
    simultaneously [ˌsɪmlˈteɪniəsli]:adv. 同时地
    exclusive [ɪkˈskluːsɪv]:adj. 独有的,排外的,专一的 n. 独家新闻,独家经营的项目,排外者
    semantics [sɪˈmæntɪks]:n. 语义学,语义论
    recursive [rɪˈkɜːsɪv]:adj. 递归的,循环的
    

    1. std::mutex::lock

    void lock(); - since C++11

    Locks the mutex. If another thread has already locked the mutex, a call to lock will block execution until the lock is acquired.
    锁定 mutex。若另一线程已锁定 mutex,则到 lock 的调用将阻塞执行,直至获得锁。

    If lock is called by a thread that already owns the mutex, the behavior is undefined: for example, the program may deadlock. An implementation that can detect the invalid usage is encouraged to throw a std::system_error with error condition resource_deadlock_would_occur instead of deadlocking.
    lock 为已占有 mutex 的线程调用,则行为未定义:例如,程序可能死锁。鼓励能检测非法使用的实现抛出以 resource_deadlock_would_occur 为错误条件的 std::system_error,而不是死锁。

    Prior unlock() operations on the same mutex synchronize-with (as defined in std::memory_order) this operation.
    同一 mutex 上先前的 unlock() 操作同步于 (定义于 std::memory_order) 此操作。

    Lock mutex - 锁定 mutex

    The calling thread locks the mutex, blocking if necessary:
    调用线程锁定 mutex,必要时阻塞:

    • If the mutex isn’t currently locked by any thread, the calling thread locks it (from this point, and until its member unlock is called, the thread owns the mutex).
      如果 mutex 当前未被任何线程锁定,则调用线程将其锁定 (从这此时开始,直到调用其成员 unlock,该线程拥有 mutex)。

    • If the mutex is currently locked by another thread, execution of the calling thread is blocked until unlocked by the other thread (other non-locked threads continue their execution).
      如果 mutex 当前被另一个线程锁定,则调用线程的执行将被阻止,直到被另一个线程解锁 (其他非锁定线程继续执行)。

    • If the mutex is currently locked by the same thread calling this function, it produces a deadlock (with undefined behavior). See recursive_mutex for a mutex type that allows multiple locks from the same thread.
      如果 mutex 当前被调用此函数的同一线程锁定,则会产生死锁 (行为未定义)。请参阅 recursive_mutex 以获取 mutex 类型,该类型允许来自同一线程的多个锁。

    All lock and unlock operations on the mutex follow a single total order, with all visible effects synchronized between the lock operations and previous unlock operations on the same object.
    互斥锁上的所有 lock and unlock 操作都遵循一个总顺序,所有可见效果在同一对象上的锁定操作和先前的解锁操作之间同步。

    The non-member function lock allows to lock more than one mutex object simultaneously, avoiding the potential deadlocks that can happen when multiple threads lock/unlock individual mutex objects in different orders.
    非成员函数 lock 允许同时锁定多个 mutex 对象,避免了当多个线程以不同顺序 lock/unlock 单个 mutex 对象时可能发生的死锁。

    Note that the order in which different concurrent locks are scheduled to return is unspecified, and not necessarily related to the order in which they are locked (depending on the system and library implementation).
    请注意,被调度的不同并发锁返回的顺序是不确定的,并且不一定与它们被锁定的顺序有关 (取决于系统和库的实现)。

    intermingle [ˌɪntəˈmɪŋɡl]:vt. 使混合,使搀和 vi. 混合,掺杂
    

    Throws std::system_error when errors occur, including errors from the underlying operating system that would prevent lock from meeting its specifications. The mutex is not locked in the case of any exception being thrown.
    错误发生时抛出 std::system_error,包括来自底层操作系统的错误,这些错误会导致锁无法满足其规范。在抛出任何异常的情况下,不锁定 mutex

    lock() is usually not called directly: std::unique_lock and std::lock_guard are used to manage exclusive locking.
    通常不直接调用 lock():用 std::unique_lockstd::lock_guard 管理排他性锁定。

    2. Parameters

    none

    3. Return value

    none

    4. Example - 示例

    4. 1 std::mutex::lock/unlock

    //============================================================================
    // Name        : std::mutex::lock/unlock
    // Author      : Yongqiang Cheng
    // Version     : Version 1.0.0
    // Copyright   : Copyright (c) 2019 Yongqiang Cheng
    // Description : Hello World in C++, Ansi-style
    //============================================================================
    
    #include <iostream>       // std::cout
    #include <thread>         // std::thread
    #include <mutex>          // std::mutex
    
    std::mutex mtx;           // mutex for critical section
    
    void print_thread_id(int id)
    {
    	// critical section (exclusive access to std::cout signaled by locking mtx):
    	mtx.lock();
    	std::cout << "thread #" << id << "-->";
    	std::cout << "thread #" << id << '\n';
    	mtx.unlock();
    }
    
    int main()
    {
    	std::thread threads[10];
    	// spawn 10 threads:
    	for (int i = 0; i < 10; ++i)
    	{
    		threads[i] = std::thread(print_thread_id, i + 1);
    	}
    
    	for (auto& th : threads)
    	{
    		th.join();
    	}
    
    	return 0;
    }
    
    

    Possible output (order of lines may vary, but they are never intermingled):
    可能的输出 (行的顺序可能会有所不同,但是它们永远不会混合在一起):

    thread #1-->thread #1
    thread #7-->thread #7
    thread #2-->thread #2
    thread #9-->thread #9
    thread #4-->thread #4
    thread #6-->thread #6
    thread #5-->thread #5
    thread #8-->thread #8
    thread #3-->thread #3
    thread #10-->thread #10
    
    

    4.2 std::mutex::lock

    //============================================================================
    // Name        : std::mutex::lock
    // Author      : Yongqiang Cheng
    // Version     : Version 1.0.0
    // Copyright   : Copyright (c) 2019 Yongqiang Cheng
    // Description : Hello World in C++, Ansi-style
    //============================================================================
    
    #include <iostream>
    #include <chrono>
    #include <thread>
    #include <mutex>
    
    int g_num = 0;  // protected by g_num_mutex
    std::mutex g_num_mutex;
    
    void slow_increment(int id)
    {
    	for (int i = 0; i < 5; ++i)
    	{
    		g_num_mutex.lock();
    		++g_num;
    		std::cout << id << " => " << g_num << '\n';
    		g_num_mutex.unlock();
    
    		std::this_thread::sleep_for(std::chrono::seconds(1));
    	}
    }
    
    int main()
    {
    	std::thread t1(slow_increment, 0);
    	std::thread t2(slow_increment, 1);
    	t1.join();
    	t2.join();
    
    	return 0;
    }
    
    
    1 => 1
    0 => 2
    1 => 3
    0 => 4
    1 => 5
    0 => 6
    1 => 7
    0 => 8
    1 => 9
    0 => 10
    
    

    5. Data races - 数据竞争

    The mutex object is modified as an atomic operation (causing no data races).
    互斥对象被修改为原子操作 (不引起数据竞争)。

    6. Exception safety - 异常安全性

    Basic guarantee: if an exception is thrown by this member function, the mutex object is left in a valid state. Further, a lock is never acquired by the thread that made the throwing call.
    基本保证:如果此成员函数引发异常,则 mutex 对象将保持有效状态。此外,进行抛出调用的线程永远不会获得锁定。

    If the mutex is already locked by the current thread, calling this function causes a deadlock (undefined behavior): on certain library implementations, this causes the function to fail.
    如果 mutex 已被当前线程锁定,则调用此函数将导致死锁 (未定义行为):在某些库实现中,这将导致函数失败。

    If the call fails, a system_error exception is thrown:
    如果调用失败,将抛出 system_error 异常:

    exception typeerror conditiondescription
    system_errorerrc::resource_deadlock_would_occurA deadlock was detected (implementations may detect certain cases of deadlock). - 检测到死锁 (实现可能检测到某些死锁情况)。
    system_errorerrc::operation_not_permittedThe thread does not have privileges to perform the operation. - 该线程没有执行该操作的权限。
    system_errorerrc::device_or_resource_busyThe native handle type manipulated is already locked. - 操作的本机句柄类型已被锁定。

    Depending on the library implementation, this member function may also throw exceptions to report other situations.
    根据库的实现,此成员函数还可能引发异常以报告其他情况。

    Reference

    http://www.cplusplus.com/reference/mutex/mutex/lock/
    https://en.cppreference.com/w/cpp/thread/mutex/lock

    展开全文
  • std::atomic和std::mutex区别

    千次阅读 2022-03-12 18:31:50
    std::atomic介绍​ ​模板类std::atomic是C++11提供的原子操作类型,头文件 #include<atomic>。​在多线程调用下,利用std::atomic可实现数据结构的无锁设计。​​ ​和互斥量的不同之处在于,std::atomic...
  • std::mutex::unlock

    2020-02-23 16:49:43
    std::mutex::unlock Defined in header <mutex> - 定义于头文件 <mutex> public member function - 公开成员函数 mutex:n. 互斥,互斥元,互斥体,互斥量 synchronization [ˌsɪŋkrənaɪˈzeɪʃn]...
  • 1、std::mutex(互斥对象) 简单的信号量,不支持递归 原理:A mutex is a lockable object that is designed to signal when critical sections of code need exclusive access, preventing other threads with the...
  • 线程并发中std::mutex和boost::mutex::scoped_lock的使用

    千次阅读 多人点赞 2020-11-03 17:17:23
    编译问题 1)使用std::mutex的时候,如果用g++命令编译,记得加上-lpthread g++ mutex.cpp -o mutex -std=c++11 -lpthread 2)使用boost::mutex::scoped_lock的时候,使用g++编译,命令如下: g++ mutex.cpp -o ...
  • std::mutex std::lock_guard
  • key world: std::shared_mutexstd::mutex、performance、benchmark、性能测试 shared_mutex的适用场景比较特殊:一个或多个读线程同时读取共享资源,且只有一个写线程来修改这个资源,这种情况下才能从shared_...
  • 1. 头文件 #include <mutex> 2. 分类 std::mutex——最基本的mutexstd::recursive_mutex...std::mutex 是C++11 中最基本的互斥量,std::mutex 对象提供了独占所有权的特性——即非递归锁,而 std::recurs
  • 1、Mutex分类 2、std::mutex介绍 3、std::recursive_mutex介绍 4、std::time_mutex介绍 5、std::recursive_timed_mutex介绍 6、总结
  • c++11 多线程 mutex lock unique_lock lock_guard
  • C/C++编程:std::mutex 详解

    千次阅读 2020-07-15 10:04:18
    头文件中,所以如果你需要使用 std::mutex,就必须包含 <mutex>头文件。 <mutex>头文件介绍 1、Mutex系列类 std::mutex,最基本的Mutexstd::recursive_mutex,递归Mutexstd::time_mutex,定时...
  • C++ std::mutex std::lock_guard

    千次阅读 2019-04-22 17:54:00
    mutex:http://www.cplusplus.com/reference/mutex/mutex/?kw=mutex lock_guard:http://www.cplusplus.com/reference/mutex/lock_guard/?kw=lock_guard class <mutex> std::mutex class mutex; Mutex cl...
  • 深入应用C++11》笔记-互斥量std::mutex、锁std::lock_guard ... 上一篇:《深入应用C++11》笔记-线程std::thread C++11中提供了std::mutex互斥量,共包含四种类型: ...std::mutex:最基本的mutex类。 std...
  • 头文件中,所以使用std::mutex就必须包含<mutex>头文件。 <mutex>头文件介绍 Mutex系列类(四种) std::mutex, 最基本的Mutex类。 std::recursive_mutex,递归Mutex类。 std::time_mutex,定时Mutex...
  • C++ 互斥量std::mutex简单介绍

    千次阅读 2020-12-23 17:19:54
    std::mutex 互斥量是一个可以处于两态之一的变量:解锁和加锁。这样,只需要一个二进制位表示它,不过实际上,常常使用一个整型量,0表示解锁,而其他所有的值则表示加锁。互斥量使用两个过程。当一个线程(或进程)...
  • #include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex, std::unique_lock #include <condition_variable...
  • std::mutex 头文件是<mutex>,mutex是用来保证线程同步的,防止不同的线程同时操作同一个共享数据。使用比较简单,定义之后,调用加锁解锁函数即可。 std::mutex m; m.lock(); //被保护的操作 m_unlock(); ...
  • C++11并发之std::mutex

    2020-03-06 17:02:56
    C++11并发之std::mutex 知识链接: C++11并发之std::thread 本文概要: 1、<mutex> 头文件。 2、std::mutex。 3、std::recursive_mutex。 4、std::time_mutex。 5、std::lock_guard 与 std::unique_lock。 ...
  • std::mutex

    2021-03-24 20:59:30
    std::mutex 是C++11 中最基本的互斥量,std::mutex 对象提供了独占所有权的特性——即不支持递归地对 std::mutex 对象上锁,而 std::recursive_lock 则可以递归地对互斥量对象上锁。 下面给出一个与 std::mutex ...
  • std::mutex 标准库的互斥锁;CRITICAL_SECTION Windows提供的临界区;QMutex Qt提供的互斥锁封装,显然,Qt封装的效率一般不如前两者。 参照这篇文章:https://www.iteye.com/blog/aigo-1908084 和他的结论差不多...
  • 通常不直接使用 mutex, lock_guard 更加安全, 更加方便。 lock_guard简化了 lock/unlock 的写法, lock_guard 在构造时自动锁定互斥量, 而在退出作用域...std::mutex myLock; void func() { { std::lock_guard<st
  • std::mutex 是C++11 中最基本的互斥量,std::mutex 对象提供了独占所有权的特性——即不支持递归地对 std::mutex 对象上锁,而 std::recursive_lock 则可以递归地对互斥量对象上锁。 Mutex 分类 std::mutex,最...
  • std::mutexstd::lock_guard

    2022-04-27 11:55:01
    std::mutex是互斥锁,它是一种可锁定的对象,它被设计用来在关键代码段需要独占访问时发出信号,防止具有相同保护的其他线程并发执行并访问相同的内存位置。互斥对象提供独占性,不支持递归性(也就是说,一个线程不...
  • C++11——std::mutex

    千次阅读 2019-09-15 10:43:11
    互斥量 ...当一个线程(或进程)需要访问临界区时,它调用mutex_lock。如果该互斥量当前是解锁的(即临界区可用),此调用成功,调用线程可以自由进入该临界区。 #include <iostream> #inc...
  • std::mutex - cppreference

    2020-02-23 09:53:19
    mutex:n. 互斥,互斥元,互斥体,互斥量 synchronization [ˌsɪŋkrənaɪˈzeɪʃn]:n. 同步,同时性 primitive [ˈprɪmətɪv]:adj. 原始的,远古的,简单的,粗糙的 n. 原始人 simultaneously [ˌsɪmlˈte...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,013
精华内容 14,405
关键字:

std::mutex

友情链接: subdivision.rar