当前位置: 首页 > news >正文

做美术鉴赏网站的心得wordpress免费装修主题

做美术鉴赏网站的心得,wordpress免费装修主题,网站建设报价单 下载,接app推广本文介绍C 并发中使用的其他类型的锁,包括unique_lock,shared_lock, 以及recursive_lock等。shared_lock和unique_lock比较常用,而recursive_lock用的不多,或尽可能规避用这种锁。 unique_lock unique_lock和lock_guard基本用法…
  • 本文介绍C++ 并发中使用的其他类型的锁,包括unique_lock,shared_lock, 以及recursive_lock等。shared_lock和unique_lock比较常用,而recursive_lock用的不多,或尽可能规避用这种锁。

unique_lock

  • unique_lock和lock_guard基本用法相同,构造时默认加锁,析构时默认解锁,但unique_lock有个好处就是可以手动解锁。这一点尤为重要,方便我们控制锁住区域的粒度(加锁的范围大小),也能支持和条件变量配套使用,至于条件变量我们之后再介绍,本文主要介绍锁的相关操作。

#include<iostream>
#include<mutex>
#include<stack>
#include<memory>
#include<thread>
using std::cout;
using std::endl;//unique_lock   开始
std::mutex mtx;
int shared_data = 0;
void use_unique() {//lock可自动解锁,也可手动解锁std::unique_lock<std::mutex> lock(mtx);std::cout << "lock success" << std::endl;shared_data++;lock.unlock();
}// 我们可以通过unique_lock的owns_lock判断是否持有锁
//可判断是否占有锁
void owns_lock() {//lock可自动解锁,也可手动解锁std::unique_lock<std::mutex> lock(mtx);shared_data++;if (lock.owns_lock()) {std::cout << "owns lock" << std::endl;     // True}else {std::cout << "doesn't own lock" << std::endl;}lock.unlock();if (lock.owns_lock()) {std::cout << "owns lock" << std::endl;}else {std::cout << "doesn't own lock" << std::endl;  // True}
}//unique_lock可以延迟加锁
//可以延迟加锁
void defer_lock() {//延迟加锁std::unique_lock<std::mutex> lock(mtx, std::defer_lock);if (lock.owns_lock()) {std::cout << "owns lock" << std::endl;     // False}if (lock.owns_lock()) {std::cout << "owns lock" << std::endl;}else {std::cout << "doesn't own lock" << std::endl;  // True}//可以加锁lock.lock();//可以自动析构解锁,也可以手动解锁lock.unlock();
}//unique_lock   结束
int main()
{//use_unique();//owns_lock();defer_lock();return 0;
}
  • 整合运用
#include<iostream>
#include<mutex>
#include<stack>
#include<memory>
#include<thread>
using std::cout;
using std::endl;//unique_lock   开始
std::mutex mtx;
int shared_data = 0;
void use_unique() {//lock可自动解锁,也可手动解锁std::unique_lock<std::mutex> lock(mtx);std::cout << "lock success" << std::endl;shared_data++;lock.unlock();
}// 我们可以通过unique_lock的owns_lock判断是否持有锁
//可判断是否占有锁
void owns_lock() {//lock可自动解锁,也可手动解锁std::unique_lock<std::mutex> lock(mtx);shared_data++;if (lock.owns_lock()) {std::cout << "owns lock" << std::endl;     // True}else {std::cout << "doesn't own lock" << std::endl;}lock.unlock();if (lock.owns_lock()) {std::cout << "owns lock" << std::endl;}else {std::cout << "doesn't own lock" << std::endl;  // True}
}//unique_lock可以延迟加锁
//可以延迟加锁
void defer_lock() {//延迟加锁std::unique_lock<std::mutex> lock(mtx, std::defer_lock);if (lock.owns_lock()) {std::cout << "owns lock" << std::endl;     // False}if (lock.owns_lock()) {std::cout << "owns lock" << std::endl;}else {std::cout << "doesn't own lock" << std::endl;  // True}//可以加锁lock.lock();//可以自动析构解锁,也可以手动解锁lock.unlock();
}//同时使用owns和defer
void use_own_defer() {std::unique_lock<std::mutex>  lock(mtx);// 判断是否拥有锁if (lock.owns_lock()){std::cout << "Main thread has the lock." << std::endl; // True}else{std::cout << "Main thread does not have the lock." << std::endl;}std::thread t([]() {std::unique_lock<std::mutex> lock(mtx, std::defer_lock);// 判断是否拥有锁if (lock.owns_lock()){std::cout << "Thread has the lock." << std::endl;}else{std::cout << "Thread does not have the lock." << std::endl;// True}// 加锁lock.lock();// 判断是否拥有锁if (lock.owns_lock()){std::cout << "Thread has the lock." << std::endl; // // True}else{std::cout << "Thread does not have the lock." << std::endl;}// 解锁lock.unlock();});lock.unlock();t.join();
}
//unique_lock   结束
int main()
{//use_unique();//owns_lock();//defer_lock();use_own_defer();return 0;
}
  • 和lock_guard一样,unique_lock也支持领养锁

//同样支持领养操作
void use_own_adopt() {mtx.lock();std::unique_lock<std::mutex> lock(mtx, std::adopt_lock);if (lock.owns_lock()) {std::cout << "owns lock" << std::endl;}else {std::cout << "does not have the lock" << std::endl;}lock.unlock();
}
  • 尽管是领养的,但是打印还是会出现owns lock,因为不管如何锁被加上,就会输出owns lock。既然unique_lock支持领养操作也支持延迟加锁,那么可以用两种方式实现前文lock_guard实现的swap操作。

//之前的交换代码可以可以用如下方式等价实现
int a = 10;
int b = 99;
std::mutex  mtx1;
std::mutex  mtx2;
void safe_swap() {std::lock(mtx1, mtx2);std::unique_lock<std::mutex> lock1(mtx1, std::adopt_lock);std::unique_lock<std::mutex> lock2(mtx2, std::adopt_lock);std::swap(a, b);//错误用法//mtx1.unlock();//mtx2.unlock();
}
void safe_swap2() {std::unique_lock<std::mutex> lock1(mtx1, std::defer_lock);std::unique_lock<std::mutex> lock2(mtx2, std::defer_lock);//需用lock1,lock2加锁std::lock(lock1, lock2);//错误用法//std::lock(mtx1, mtx2);std::swap(a, b);
}
  • 大家注意一旦mutex被unique_lock管理,加锁和释放的操作就交给unique_lock,不能调用mutex加锁和解锁,因为锁的使用权已经交给unique_lock了。我们知道mutex是不支持移动和拷贝的,但是unique_lock支持移动,当一个mutex被转移给unique_lock后,可以通过unique_ptr转移其归属权.
    注意延迟加锁和领养锁之后,就只能使用后者进行解锁了,不能使用原生的锁进行解锁操作

/转移互斥量所有权
//互斥量本身不支持move操作,但是unique_lock支持
std::unique_lock <std::mutex>  get_lock() {std::unique_lock<std::mutex>  lock(mtx);shared_data++;return lock;
}
void use_return() {std::unique_lock<std::mutex> lock(get_lock());shared_data++;
}

锁的粒度表示加锁的精细程度,一个锁的粒度要足够大,保证可以锁住要访问的共享数据。同时一个锁的粒度要足够小,保证非共享数据不被锁住影响性能。而unique_ptr则很好的支持手动解锁。

void precision_lock() {std::unique_lock<std::mutex> lock(mtx);shared_data++;lock.unlock();//不设计共享数据的耗时操作不要放在锁内执行std::this_thread::sleep_for(std::chrono::seconds(1));lock.lock();shared_data++;
}

共享锁

  • 试想这样一个场景,对于一个DNS服务,我们可以根据域名查询服务对应的ip地址,它很久才更新一次,比如新增记录,删除记录或者更新记录等。平时大部分时间都是提供给外部查询,对于查询操作,即使多个线程并发查询不加锁也不会有问题,但是当有线程修改DNS服务的ip记录或者增减记录时,其他线程不能查询,需等待修改完再查询。或者等待查询完,线程才能修改。也就是说读操作并不是互斥的,同一时间可以有多个线程同时读,但是写和读是互斥的,写与写是互斥的,简而言之,写操作需要独占锁。而读操作需要共享锁。

  • 要想使用共享锁,需使用共享互斥量std::shared_mutex,std::shared_mutex是C++17标准提出的。C++14标准可以使用std::shared_time_mutex,

  • std::shared_mutex 和 std::shared_timed_mutex 都是用于实现多线程并发访问共享数据的互斥锁,但它们之间存在一些区别:

  • std::shared_mutex:

    • 提供了 lock(), try_lock(), 和 try_lock_for() 以及 try_lock_until() 函数,这些函数都可以用于获 取互斥锁。
    • 提供了 try_lock_shared()lock_shared() 函数,这些函数可以用于获取共享锁。
    • std::shared_mutex 被锁定后,其他尝试获取该锁的线程将会被阻塞,直到该锁被解锁。
  • std::shared_timed_mutex:

    • std::shared_mutex 类似,也提供了 lock(), try_lock(), 和 try_lock_for() 以及 try_lock_until() 函数用于获取互斥锁。
    • std::shared_mutex 不同的是,它还提供了 try_lock_shared()lock_shared() 函数用于获取共享锁,这些函数在尝试获取共享锁时具有超时机制。
    • std::shared_timed_mutex 被锁定后,其他尝试获取该锁的线程将会被阻塞,直到该锁被解锁,这与 std::shared_mutex 相同。然而,当尝试获取共享锁时,如果不能立即获得锁,std::shared_timed_mutex 会设置一个超时,超时过后如果仍然没有获取到锁,则操作将返回失败。

C++11标准没有共享互斥量,可以使用boost提供的boost::shared_mutex。如果我们想构造共享锁,可以使用std::shared_lock,如果我们想构造独占锁, 可以使用std::lock_gurad.我们用一个类DNService代表DNS服务,查询操作使用共享锁,而写操作使用独占锁,可以是如下方式的。

在这里插入图片描述


#include <iostream>
#include <memory>
#include<mutex>
#include<thread>
#include<map>
#include <shared_mutex> // std::shared_mutex(C++17引入)   std::shared_lock(C++14引入)
class DNService {
public:DNService() {}//读操作采用共享锁std::string QueryDNS(std::string dnsname) {std::shared_lock<std::shared_mutex> shared_locks(_shared_mtx);auto iter = _dns_info.find(dnsname);if (iter != _dns_info.end()) {return iter->second;}return "";}//写操作采用独占锁void AddDNSInfo(std::string dnsname, std::string dnsentry) {std::lock_guard<std::shared_mutex>  guard_locks(_shared_mtx);_dns_info.insert(std::make_pair(dnsname, dnsentry));}
private:std::map<std::string, std::string> _dns_info;mutable std::shared_mutex  _shared_mtx;
};

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

递归锁

有时候我们在实现接口的时候内部加锁,接口内部调用完结束自动解锁。会出现一个接口调用另一个接口的情况,如果用普通的std::mutex就会出现卡死,因为嵌套加锁导致卡死。


#include <iostream>
#include <mutex>
#include <thread>class BankAccount {
private:std::mutex mtx;double balance = 1000.0;public:// 接口1:存款void deposit(double amount) {std::lock_guard<std::mutex> lock(mtx);balance += amount;std::cout << "Deposited " << amount << ", new balance: " << balance << std::endl;}// 接口2:取款void withdraw(double amount) {std::lock_guard<std::mutex> lock(mtx);if (balance >= amount) {balance -= amount;std::cout << "Withdrew " << amount << ", new balance: " << balance << std::endl;} else {std::cout << "Insufficient funds for withdrawal of " << amount << std::endl;}}// 接口3:转账(会调用存款和取款接口)void transfer(BankAccount& toAccount, double amount) {std::lock_guard<std::mutex> lock(mtx);  // 第一次加锁this->withdraw(amount);  // 内部再次尝试加锁 - 这里会导致死锁!toAccount.deposit(amount);}
};int main() {BankAccount accountA;BankAccount accountB;// 这个调用会导致死锁accountA.transfer(accountB, 100.0);return 0;
}

在这里插入图片描述

但是我们可以使用递归锁。


#include <iostream>
#include <mutex>class BankAccount {
private:std::recursive_mutex mtx;  // 关键修改:使用可重入锁double balance = 1000.0;public:void deposit(double amount) {std::lock_guard<std::recursive_mutex> lock(mtx);balance += amount;std::cout << "Deposited " << amount << ", new balance: " << balance << std::endl;}void withdraw(double amount) {std::lock_guard<std::recursive_mutex> lock(mtx);if (balance >= amount) {balance -= amount;std::cout << "Withdrew " << amount << ", new balance: " << balance << std::endl;}else {std::cout << "Insufficient funds for withdrawal of " << amount << std::endl;}}void transfer(BankAccount& toAccount, double amount) {std::lock_guard<std::recursive_mutex> lock(mtx);  // 第一次加锁this->withdraw(amount);  // 内部再次加锁 - 现在可以正常工作toAccount.deposit(amount);}
};int main() {BankAccount accountA;BankAccount accountB;accountA.transfer(accountB, 100.0);return 0;
}

但我个人并不推荐递归锁,可以从设计源头规避嵌套加锁的情况,我们可以将接口相同的功能抽象出来,统一加锁。下面的设计演示了如何使用递归锁
//不推荐采用递归锁,使用递归锁说明设计思路并不理想,需优化设计
//推荐拆分逻辑,将共有逻辑拆分为统一接口

#include <iostream>
#include <mutex>class BankAccount {
private:std::mutex mtx;  // 使用普通互斥量double balance = 1000.0;// 不加锁的核心实现方法void unsafe_deposit(double amount) {balance += amount;std::cout << "Deposited " << amount << ", new balance: " << balance << std::endl;}// 不加锁的核心实现方法bool unsafe_withdraw(double amount) {if (balance >= amount) {balance -= amount;std::cout << "Withdrew " << amount << ", new balance: " << balance << std::endl;return true;}std::cout << "Insufficient funds for withdrawal of " << amount << std::endl;return false;}public:// 线程安全的公共接口void deposit(double amount) {std::lock_guard<std::mutex> lock(mtx);unsafe_deposit(amount);}void withdraw(double amount) {std::lock_guard<std::mutex> lock(mtx);unsafe_withdraw(amount);}void transfer(BankAccount& toAccount, double amount) {// 同时锁定两个账户,避免死锁std::unique_lock<std::mutex> lock1(mtx, std::defer_lock);std::unique_lock<std::mutex> lock2(toAccount.mtx, std::defer_lock);std::lock(lock1, lock2);  // 原子化加锁if (unsafe_withdraw(amount)) {toAccount.unsafe_deposit(amount);std::cout << "Transferred " << amount << " successfully" << std::endl;}}
};
int main() {BankAccount accountA;BankAccount accountB;// 这个调用会导致死锁accountA.transfer(accountB, 100.0);return 0;
}

在这里插入图片描述

http://www.dtcms.com/a/444783.html

相关文章:

  • 特色网站设计网站建设 话术
  • 网站建设的行业资讯国外手机网站欣赏
  • 度娘网站灯笼要咋做呢网站的模块怎么做
  • 个人博客网站设计模板wordpress链接替换
  • 湖南哪里有做网站的网站小图标素材
  • 天津网站建设外贸短视频公司网站建设方案
  • 怎么按照屏幕比例做网站适应衡水网站建设联系电话
  • 学校网站备案怎么做营销型网站要多少钱
  • 网站建设与管理收获自助建站信息网
  • 电脑个人网站怎么做WordPress开cdn支付
  • 电子商务网站建设技术有哪些方面网站视频弹窗广告代码
  • 带数据库的网站怎么建jsp和php哪个做网站快
  • 英文外贸商城网站设计超简单手工小制作
  • 嘉兴网站公司哪家好软件技术毕业做什么工作
  • 工信部资质查询网站天津小程序网站开发公司
  • 网站后台申请邮箱天津做网站的公司
  • 怎么注册自己网站wordpress word粘贴
  • 如何快速提高网站关键词排名wordpress 退出登录
  • 厦门网站推广公司网站建设化学图片
  • 怎样选择 网站建设桐乡市城乡规划建设局网站
  • 开一家网站建设公司要多少钱wordpress网站制作app
  • 网站建设ssc源码做网站数据库设计
  • 石家庄网站seo服务医疗网站建设策划
  • 网站开发一般用什么服务器网站跳出率因素
  • 设计公司网站设计标签下载wordpress
  • 怎么建设一个购物网站西安 房产网站建设
  • 网站设计方案案例分析微信网页版注册
  • 福田手机网站建设wordpress的标签设置主页
  • 网站的营销与推广建站是什么东西
  • 求个网站你懂我的意思2021网站建设制作周期