安全指针

本文探讨了在并发环境中使用安全指针与rw-lock结合的方法,对比了基于锁的算法和无锁算法的优缺点。内容涉及死锁问题、可组合性、无锁容器和事务性内存,并提供了两种解决方案来解决死锁问题:静态link_safe_ptrs和lock_timed_any_infinity。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

经过测试:

Windows x86_64(MSVS 2013和2015)
  Linux x86_64(g ++ 6.3.0和clang 3.8.0)
  此代码在在线编译器中:http : //coliru.stacked-crooked.com/a/a97a84ff26c6e9ee

将safe_ptr <>与rw-lock一起使用。

要将安全指针与rw-lock而不是unique-lock一起使用,只需 #include <safe_ptr.h> 编写so shared_mutex_safe_ptr<std::map<int,int>>而不是即可 safe_ptr<std::map<int,int>>。或者更好地编写contfree_safe_ptr<std::map<int,int>> ptr;使用更快的共享互斥量的方法,我们将在第二篇文章中对其进行描述。然后,使用 slock_safe_ptr(ptr)->find(5);或auto const& ptr_read = ptr; ptr_read->find(5); 称为只读共享锁-我们将在第三篇文章中介绍这些方式。

其他背景

可组合性和僵局。

由于我们在上文中将锁用于线程安全,因此我们的算法称为基于锁。

在无锁容器中没有死锁,基于事务性内存的算法方面是否真的还不错,并且现代RDBMS中是否存在死锁:MSSQL(基于锁的IL)和Oracle(多版本并发控制)?

无锁算法不允许一次原子地更改多个容器。RDBMS的死锁问题与基于锁的算法相同,它们通常通过锁超时或锁图来解决。并且C ++标准中新的事务安全部分不允许您安全使用复杂算法,例如std :: map <>。

无锁算法不具有可组合操作的属性-几种无锁算法的联合原子使用。也就是说,无法一次更改或读取多个无锁数据结构。例如,您可以使用来自libCDS的关联数组的无锁容器,它们将分别是线程安全的。但是,如果您想一次用几个无锁容器自动执行操作并保持一致性,则不能这样做,因为它们的API不能同时在多个容器上提供无锁操作的功能。当您更改或读取一个容器时,那时将已经更改另一个容器。为避免这种情况,您将需要使用锁,在这种情况下,它将是基于锁的容器,这意味着它们将具有基于锁的算法的所有问题,即可能出现死锁的问题。另外,有时仅在使用一个容器的情况下使用锁:

http://libcds.sourceforge.net/doc/cds-api/namespacecds_1_1sync.html
  https://github.com/khizmax/libcds/tree/master/cds/lock
  https://github.com/khizmax/libcds/tree/master/cds/sync
  在事务性RDBMS中,例如MSSQL(基于锁)和Oracle(多版本并发控制),也使用锁,这就是死锁存在问题的原因,例如,可以通过构建锁来自动解决死锁问题。图形并找到循环等待,或通过设置锁定等待时间,从tbl中选择col,其中(…)中的id用于更新等待30;如果经过了潜在时间或在锁定图中发现了死锁,则发生事务之一的回滚-也就是说,取消该事务已经进行的所有更改,解锁所有已锁定的事务; 然后您可以尝试从一开始就执行事务(如此多次):

Oracle数据库在线文档11g第1版(11.1)-死锁:https : //docs.oracle.com/cd/B28359_01/server.111/b28318/consist.htm#i5337
  Oracle锁:https : //docs.oracle.com/cd/B28359_01/server.111/b28318/consist.htm#i5249

如您所见,任何表达式都使用排他的不兼容锁:Insert / Update / Delete / Select-For-Update

MSSQL检测和结束死锁:https 😕/technet.microsoft.com/zh-cn/library/ms178104( v= sql.105).aspx
  MS SQL锁:https://technet.microsoft.com/zh-cn/library/ms186396(v = sql.105).aspx

反过来,与无锁容器不同,事务性内存可以自动处理许多容器/数据。也就是说,事务性内存具有可组合操作功能。在内部,使用了悲观锁(具有死锁冲突可能性)或乐观锁(更可能是具有竞争性修改的冲突修改)。并且在发生任何冲突的情况下,交易从一开始就自动取消并重复,这需要多次重复执行所有操作-这会导致高昂的间接费用。他们正在尝试通过在CPU级别上创建硬件事务性存储器来降低开销成本,但是到目前为止,尽管英特尔已经在Haswell CPU中添加了硬件事务性存储器,但仍没有实现令人满意的性能的实现。他们还承诺将事务性内存包含在C ++标准中,但仅在将来,到目前为止,它仅用作实验性,不支持使用std :: map。也就是说,到目前为止,一切仅在理论上是好的。但是在将来,这很可能会取代通常的同步方法。

最终:

如果在实现时未提供这样的选项,则不构成基于锁的算法。但是可以实现此选项,我们在前面的部分中已成功实现。
  无锁算法不是组合的,没有锁的组合是非常复杂的任务。但是使用锁时,这种算法将不再是无锁的,并且存在永久死锁的风险。减肥食谱:www.sheonline.cn
  RDBMS:MSSQL(基于锁的IL)和Oracle(MVCC)-可能存在死锁,可以通过锁图或超时来消除死锁。
  到目前为止,来自C ++标准实验部分的事务性内存仅限于仅在最简单的算法中使用,并且不允许在std :: map <>方法或更复杂的算法中使用算法。
  结论:死锁问题存在于表现出高性能的所有类型的算法和系统中,其中一次调用多个数据结构。因此,我们提供了2种解决方案来解决safe_ptr <>

静态link_safe_ptrs tmp_link(safe_user_accounts,safe_cash_flows_src_id,safe_cash_flows_dst_id); -将一个互斥锁用于多个容器
  lock_timed_any_infinity lock_all(safe_cash_flows_src_id,safe_cash_flows_dst_id,safe_user_accounts); -使用锁超时;时间到期后,解锁所有内容并尝试再次锁定它
  如果只有一个容器和一个递归互斥锁用于safe_ptr <>,则在safe_ptr <>中不会发生死锁,因为我们至少需要2个递归互斥锁来进行死锁(或1个非递归锁)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值