【mutex、unique

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

mutex

mutex 类是能用于保护共享数据免受从多个线程同时访问的同步原语。

  1. mtx1.lock() ,mtx1.unlock() 的使用
#include<thread>
#include<mutex>
#include<iostream>
#include<vector>
int count = 10 ;
std::mutex mtx1;
std::vector<std::thread>threads;
auto res =[]{
    mtx1.lock();
    std::cout<<++count<<"count"<<std::endl;
    mtx1.unlock();
    //unlock();
};
int main(){
    for(int i=0;i<10;i++)threads.emplace_back(res);
    for(auto &x:threads) x.join();

    return 0;
}

try_lock

例子1

#include <chrono>
#include <mutex>
#include <thread>
#include <iostream> // std::cout
 
std::chrono::milliseconds interval(100);
 
std::mutex mutex;
int job_shared = 0; // 两个线程都能修改 'job_shared',
    // mutex 将保护此变量
 
int job_exclusive = 0; // 只有一个线程能修改 'job_exclusive'
    // 不需要保护
 
// 此线程能修改 'job_shared' 和 'job_exclusive'
void job_1() 
{
    std::this_thread::sleep_for(interval); // 令 'job_2' 持锁
 
    while (true) {
        // 尝试锁定 mutex 以修改 'job_shared'
        if (mutex.try_lock()) {
            std::cout << "job shared (" << job_shared << ")\n";
            mutex.unlock();
            return;
        } else {
            // 不能获取锁以修改 'job_shared'
            // 但有其他工作可做
            ++job_exclusive;
            std::cout << "job exclusive (" << job_exclusive << ")\n";
            std::this_thread::sleep_for(interval);
        }
    }
}
 
// 此线程只能修改 'job_shared'
void job_2() 
{
    mutex.lock();
    std::this_thread::sleep_for(5 * interval);
    ++job_shared;
    mutex.unlock();
}
 
int main() 
{
    std::thread thread_1(job_1);
    std::thread thread_2(job_2);
 
    thread_1.join();
    thread_2.join();
}

2 try_lock 第二个例子

下列示例用 std::try_lock 周期地记录并重置运行于分离线程的计数器。

#include <mutex>
#include <vector>
#include <thread>
#include <iostream>
#include <functional>
#include <chrono>
 
int main()
{
    int foo_count = 0;
    std::mutex foo_count_mutex;
    int bar_count = 0;
    std::mutex bar_count_mutex;
    int overall_count = 0;
    bool done = false;
    std::mutex done_mutex;
 
    auto increment = [](int &counter, std::mutex &m,  const char *desc) {
        for (int i = 0; i < 10; ++i) {
            std::unique_lock<std::mutex> lock(m);
            ++counter;
            std::cout << desc << ": " << counter << '\n';
            lock.unlock();
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    };
 
    std::thread increment_foo(increment, std::ref(foo_count), 
        std::ref(foo_count_mutex), "foo");
    std::thread increment_bar(increment, std::ref(bar_count), 
        std::ref(bar_count_mutex), "bar");
 
    std::thread update_overall([&]() {
        done_mutex.lock();
        while (!done) {
            done_mutex.unlock();
            int result = std::try_lock(foo_count_mutex, bar_count_mutex);
            if (result == -1) {
                overall_count += foo_count + bar_count;
                foo_count = 0;
                bar_count = 0;
                std::cout << "overall: " << overall_count << '\n';
                foo_count_mutex.unlock();
                bar_count_mutex.unlock();
            }
            std::this_thread::sleep_for(std::chrono::seconds(2));
            done_mutex.lock();
        }
        done_mutex.unlock();
    });
 
    increment_foo.join();
    increment_bar.join();
    done_mutex.lock();
    done = true;
    done_mutex.unlock();
    update_overall.join();
 
    std::cout << "Done processing\n"
              << "foo: " << foo_count << '\n'
              << "bar: " << bar_count << '\n'
              << "overall: " << overall_count << '\n';
}

注意

  int result = std::try_lock(foo_count_mutex, bar_count_mutex);
  尝试锁定每个给定的可锁定 (Lockable) 对象 lock1、 lock2、 ...、 lockn 通过以从头开始的顺序调用 try_lock 。
若调用 try_lock 失败则不再进一步调用 try_lock 并对任何已锁对象调用 unlock 返回锁定失败对象的 0 底下标。
若调用 try_lock 抛出异常则在重抛前对任何已锁对象调用 unlock 。

bar: 1
foo: 1
foo: 2
bar: 2
foo: 3
overall: 5
bar: 1
foo: 1
bar: 2
foo: 2
bar: 3
overall: 10
bar: 1
foo: 1
bar: 2
foo: 2
overall: 14
bar: 1
foo: 1
bar: 2
overall: 17
foo: 1
bar: 1
foo: 2
overall: 20
Done processing
foo: 0
bar: 0
overall: 20


defer_lock

#include<iostream>
#include<thread>
#include<mutex>
#include<stdio.h>
#include<condition_variable>
/*defer_lock 防止死锁的demo*/
std::mutex mtx1;
std::mutex mtx2;
void funb()
{
    std::cout<<"线程2不获得互斥的1号锁的所有权"<<std::endl;
    std::unique_lock<std::mutex>lk1(mtx1,std::defer_lock);
    std::cout<<"线程2不获得互斥的2号锁的所有权"<<std::endl;
    std::unique_lock<std::mutex>lk2(mtx2,std::defer_lock);

    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
    std::cout<<"线程2要同时获得1号锁和2号锁的所有权"<<std::endl;
    std::lock(lk1,lk2);
    std::cout<<"线程2运行"<<std::endl;
}
void funa()
{
    //std::unique_lock<std::mutex>lock(mtx,std::defer_lock); 

    std::cout<<"线程1不获得互斥的1号锁的所有权"<<std::endl;
    std::unique_lock<std::mutex>lk1(mtx1,std::defer_lock);
    std::cout<<"线程1不获得互斥的2号锁的所有权"<<std::endl;
    std::unique_lock<std::mutex>lk2(mtx2,std::defer_lock);

    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
    std::cout<<"线程1要同时获得1号锁和2号锁的所有权"<<std::endl;
    std::lock(lk1,lk2);
    std::cout<<"线程1运行......"<<std::endl;
    //mtx.unlock();

}
int main()
{
    std::thread tha(funa);
    std::thread thb(funb);
    tha.join();
    thb.join();
    return 0;
}

结果如下
线程1不获得互斥的1号锁的所有权
线程1不获得互斥的2号锁的所有权
线程2不获得互斥的1号锁的所有权
线程2不获得互斥的2号锁的所有权
线程1要同时获得1号锁和2号锁的所有权
线程1运行…
线程2要同时获得1号锁和2号锁的所有权
线程2运行

 std::lock(lk1,lk2);
std::lock 函数模板lk1 lk2生存期到了就解除互斥。
lock概念如下

lock

锁定给定的可锁定 (Lockable) 对象 lock1 、 lock2 、 … 、 lockn 用免死锁算法避免死锁。

template< class Lockable1, class Lockable2, class… LockableN > void
lock( Lockable1& lock1, Lockable2& lock2, LockableN&… lockn );

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6