生活工程体验信仰哲学精神
投稿投诉
精神世界
探索历史
哲学文学
艺术价值
信仰创造
境界审美
体验技术
技能工具
工程信息
医学生产
生活运用
操作能力

Rust和C的并发库,傻傻分不清楚?

5月17日 皇极城投稿
  摘要:
  同时接触过Rust和C的程序员们可能会有一种感觉二者的并发特性
  很相似。不过Rust本就借鉴了许多C的设计思想,所以也不足为奇。为此,本文将具体分析二者的在并发特性上的区别,看看相同的功能下,Rust和C会分别采取什么形式
  。
  原文链接:https:blog。mou。serustcppconcurrency
  声明:本文为CSDN翻译,未经授权,禁止转载。
  作者MaraBos
  译者弯月
  出品CSDN(ID:CSDNnews)
  Rust标准库中包含的并发特性与C11非常相似:线程、原子、互斥锁、条件变量等。然而,在过去的几年里,C17和C20发布了许多与并发相关的新特性,而且在未来的几个版本中还有更多提案。
  在本文中,我们来回顾一下C的并发特性,并讨论一下相同的功能在Rust中是什么样子,以及我们应该如何实现。
  atomicref
  P0019R8在C中引入了std::atomicref。这是一种允许你将非原子对象当作原子对象的类型。例如,你可以创建一个atomicref,指向常规的int,这样就可以把它当成atomic使用了。
  C的这个方案需要定义一个新类型,其接口大部分与atomic重复,但用Rust实现相同的功能只需要一个只有一行代码的函数:Atomic::frommut。例如,你可以利用这个函数将mutu32转换为AtomicU32,在Rust中这就相当于一个别名。
  C中的atomicref类型有一定的安全要求,你需要手动支持。只要使用atomicref访问对象,则该对象的所有访问都必须通过atomicref。在有atomicref的情况下,直接访问对象会引发未定义的行为。
  然而,在Rust中,这些细节皆由借用检查器处理。编译器明白,如果以可变的形式借用u32,则在借用结束之前,不允许任何东西直接访问u32。函数frommut中的mutu32的生命周期会被作为AtomicU32的一部分保留下来。你可以根据需要随意复制AtomicU32,原始借用仅在该引用的所有副本都消失后才结束。
  目前函数frommut依然处于不稳定版本,也许是时候把它放到稳定版中了。
  通用原子类型
  在C中,std::atomic是通用的:你可以使用atomic,也可以使用atomic。另一方面,Rust中只有特定的原子类型:AtomicU32、AtomicBool、AtomicUsize等。
  C的原子类型支持任意大小的对象,无论平台支持什么。如果平台的原生原子操作无法支持对象的大小,它会自动退而采用基于锁的实现。另一方面,Rust只提供平台原生支持的类型。如果平台不支持64位的原子,则不存在AtomicU64。
  当然这有优点,也有缺点。这意味着,使用AtomicU64的Rust代码可能无法在某些平台上编译,但这也意味着不会由于某些类型悄悄地采用一个非常不同的实现而导致性能问题。此外,这也意味着,我们可以假设AtomicU64与u64在内存中的表示完全相同,因此可以使用AtomicU64::frommut之类的函数。
  在Rust中,建立一个可支持任何大小的通用Atomic的难度比较大。如果没有特化,那么如果Atomic中不包含互斥锁,Atomic就无法包含互斥锁。然而,我们可以将互斥锁存储在一个全局HashMap中,由内存地址索引。如此一来,Atomic的大小就与T相同,而且还可以在必要时使用全局HashMap中的互斥锁。
  如今流行的atomiccrate选择的就是这种方法。
  在Rust标准库中添加这种通用Atomic的提案需要讨论是否应该在nostd程序中它。常规的HashMap需要分配内存,这在nostd程序中是不可能的。固定大小的表可用于nostd程序,但由于各种原因可能并不受欢迎。
  Compareexchange对填充的处理
  P0528R3改变了compareexchange处理填充的方式。atomic的比较交换操作也会对填充位进行处理,但结果证明这种方法并不理想。如今,比较操作中不再包含填充位。
  由于Rust当前仅提供整数的原子类型,没有任何填充,因此这个变化与Rust无关。
  但是,带有compareexchange方法的Atomic提案需要讨论如何处理填充,并且应该听取这个提案的意见。
  Compareexchange的内存顺序
  在C11中,compareexchange函数要求比较成功的内存顺序至少不能弱于失败的内存顺序。不接受compareexchange(,,memoryorderrelease,memoryorderacquire)。Rust的compareexchange函数完整地复制了这个要求。
  P0418R2认为应该取消这个限制,而这个提案将在C17中推出。
  另一方面,Rust1。64也取消了相同的限制,请参见rustlangrust98383。
  互斥锁构造函数constexpr
  C的std::mutex有一个constexpr构造函数,这意味着它可以在编译时作为常量评估的一部分来构造。然而,并不是所有的实现都提供了这一点。例如,微软的std::mutex实现就不包括constexpr构造函数。要想代码具备可移植性,就不能依赖这个构造函数。
  此外,有趣的是,C的std::conditionvariable和std::sharedmutex根本没有提供constexpr构造函数。
  Rust1。0中的Mutex不包含constfnnew。再加上Rust对静态初始化的严格要求,因此很难在静态变量中使用Mutex。
  这个问题已在Rust1。63。0(rustlangrust93740)中得到了解决:所有Mutex::new、RwLock::new和Condvar::new都是const函数。
  latch和barrier
  P1135R6在C20中引入了std::latch和std::barrier。两者都允许等待多个线程到达某个点。其实latch就是一个计数器,根据每个线程递减,直到变成零。latch只能使用一次。barrier是一个更高级的版本,可以重用,并接受一个“完成函数”,当计数器达到零时自动执行。
  Rust从1。0开始有了类似的Barrier类型。但它的灵感来自pthread(pthreadbarriert)。
  Rust(以及pthread)的barrier不如C灵活。它只有一个“递减和等待”操作(wait),没有C的std::barrier自带的“只有等待”、“只有递减”以及“递减并丢弃”等功能。
  另一方面,与C不同,Rust(以及pthread)的“递减和等待”操作会指定一个线程作为组长,它可以代替“完成函数”(而且可能更灵活)。
  Rust缺少的操作其实可以随意添加。我们只需要提出这些新方法的名称。
  信号量
  P1135R6还在C20中引入了信号量:std::countingsemaphore和std::binarysemaphore。
  Rust没有通用的信号量类型,尽管它通过thread::park和unpark为每个线程分配了二进制信号量。
  我们可以使用Mutex和Condvar手动构建信号量,但大多数操作系统允许使用AtomicU32实现更高效和更小的信号量。例如,Linux上的futex和Windows上的WaitOnAddress。具体的实现取决于操作系统及其版本,以及哪些原子大小可用于这些操作。
  C的countingsemaphore是一个模板,它接受一个整数作为参数,用于传达我们希望统计的数量。例如,countingsemaphore1000的计数至少为1000,因此可以是16位或更大。binarysemaphore类型只是countingsemaphore1的别名,在某些平台上可以是单字节。
  Rust还有这种通用的类型。Rust的泛型强制实现了某种程度的一致性,因此将常量作为泛型参数时也会受到一定的限制。
  我们有单独的Semaphore32、Semaphore64等等,但这似乎有点矫枉过正。Semaphore、Semaphore,甚至是Semaphore固然没有什么问题,但以前的标准库中并没有这些。我们的原子类型就是AtomicU32、AtomicU64等等。
  如上所述,对于原子类型,我们仅提供编译平台原生支持的类型。如果我们将相同的理念应用于信号量,它就不会存在于没有futex或WaitOnAddress函数的平台上,比如macOS。如果我们根据大小建立不同的信号量类型,那么某些大小就不会出现在(某些版本的)Linux和各种BSD中了。
  如果我们希望Rust建立标准的信号量类型,首先需要了解我们是否需要不同大小的信号量,以及灵活性和可移植性需要达到什么程度。也许我们只需要一个32位的信号量(使用基于锁的替代方案),但任何此类的提议都必须包含用例和限制的详细说明。
  原子等待和通知
  P1135R6添加到C20的另一个新特性是原子wait和notify函数。
  这些函数通过标准接口,公开了Linux上的futex和Windows上的WaitOnAddress。
  然而,无论操作系统支持什么,所有平台上的所有大小的原子都可以使用这两个函数。Linux的futex(在FUTEX2之前)是32位的,但C允许使用atomic::wait。
  这其实类似于“停车场”:将内存地址映射到锁和队列的全局HashMap。这意味着,Linux上的32位等待操作可以使用基于futex的实现,而其他大小使用的实现则完全不同。
  如果我们遵循只提供原生支持的类型和函数的理念,就不会提供这样的实现了。这意味着,Linux上只有AtomicU32::wait(和AtomicI32::wait),而Windows上所有原子类型都包含wait方法。
  在Rust中,有关Atomic::wait和Atomic::notify的提案需要讨论Rust是否需要退而采用全局表。
  jthread和stoptoken
  P0660R10向C20引入了std::jthread和std::stoptoken。
  暂时抛开stoptoken不谈,其实jthread只是一个常规的std::thread,它会在销毁时自动被join。这可以避免线程意外脱离,并长期运行。但是,它也引入了一个潜在的新陷阱:即时销毁jthread对象会立即join线程,导致并行消失。
  Rust从版本1。63。0开始,加入了有作用域的线程(rustlangrust93203)。就像jthread一样,作用域线程会自动join。但是,它们之前的连接点很明确,并且是可以依赖的安全保证。此外,借用检查器明白这种安全保证,允许你安全地借用作用域线程中的局部变量,只要这些变量只在作用域中即可。
  除了自动join之外,jthreads还有一个主特点,就是stoptoken以及对应的stopsource。如果在stopsource上调用requeststop,则stoptoken上相应的stoprequested方法会返回true。我们可以利用这个方法来请求线程停止,而这一步会在join之前在jthread的析构函数中自动完成。而检查并停止token的处理则由线程的代码完成。
  到目前为止,它看起来就像一个普通的AtomicBool。
  其实,二者最大的区别在于stopcallback类型。该类型允许给停止令牌注册一个回调函数,也就是一个“停止函数”。使用相应的stopsource请求停止就可以执行该函数。实际上,我们可以利用这个函数来停止或取消线程。
  在Rust中,我们可以将类似AtomicBool的功能添加到thread::scope的Scope对象中。只需一个简单的函数isfinished(self)bool或stoprequested(self)bool即可,用于指示主范围函数是否已完成。然后就可以结合requeststop(self)方法从任何地方发送请求。
  stopcallback的功能更复杂,Rust的相关提案需要详细讨论其接口、用例和限制。
  原子浮点运算
  P0020R6在C20中添加了对原子浮点加法和减法的支持。
  在Rust中添加AtomicF32或AtomicF64也很容易,但似乎唯一支持原生原子浮点运算的平台都是一些GPU,但Rust还不支持。
  将这些类型添加到Rust的提议必须提出一些引人注目的用例。
  原子按字节内存复制
  目前,我们还无法在Rust或C中有效地实现遵守内存模型所有规则的序列锁。
  P1478R7建议在C中添加atomicloadperbytememcpy和atomicstoreperbytememcpy来解决这个问题。
  对于Rust,我写了一个提案,希望通过AtomicPerByte类型来公开这个功能:RFC3301。
  原子sharedptr
  P0718R2在C20中添加了atomic和atomic。
  引用计数指针(C中的sharedptr,Rust中的Arc)多用于并发无锁数据结构。atomic可以正确处理引用计数,从而降低了正确执行此操作的难度。
  在Rust中,我们可以添加等效的AtomicArc和AtomicWeak类型。
  然而,C的sharedptr可以为,而在Rust中则需要Option。目前还不清楚AtomicArc是否可以为,或者我们是否应该提供AtomicOptionArc。
  流行的arcswapcrate已经在Rust提供了一些变体,但是,据我所知,还没有任何提议将类似的东西添加到标准库。
  synchronizedvalue
  虽然P0290R2提出了一种名叫synchronizedvalue的类型,它结合了互斥锁和T,但最终没有被接受。
  虽然没有被C接受,但这是一个有趣的提议,因为synchronizedvalue几乎就是Rust中的Mutex。
  在C中,std::mutex不包含它保护的数据,甚至根本不知道它保护的是什么。这意味着,用户必须担负起责任,记住哪些数据受保护以及由哪个互斥锁保护,并确保每次访问“受保护”数据时都锁定正确的互斥锁。
  在RustMutex的设计中,MutexGuard的行为类似于对T的(可变)引用,可以提供更高的安全性,同时在只需要互斥锁的情况下,也可以使用Mutex。synchronizedvalue的提议是,将此模式添加到C,但使用闭包而不是互斥锁,因为C不跟踪生命周期。
  总结
  在我看来,Rust可以继续学习C的经验,但我们不能直接复制粘贴C的想法。正如我们在Mutex、作用域线程、Atomic::frommut中看到的那样,在提供相同功能时,Rust可以采用完全不同的形式。
  我们的目标不是提供与C完全相同的功能,而应该是提供Rust生态系统以及标准库需要的东西,而这可能与C用户的需求完全不同。
投诉 评论 转载

Rust和C的并发库,傻傻分不清楚?热博聚热点网 摘要:同时接触过Rust和C的程序员们可能会有一种感觉二者的并发特性很相似。不过Rust本就借鉴了许多C的设计思想,所以也不足为奇。为此,本文将具体分析二者的在并发……TCL公司VR眼镜专利获授权,无需拆下面罩调屈光度热传聚热点 企查查APP显示,9月6日,TCL科技(000100)全资子公司深圳市TCL高新技术开发有限公司申请的“VR眼镜及虚拟现实设备”专利获授权,公开号为CN217386008U。企……美国务院批准总价约11亿美元对台军售国防部回应热闻聚热点网 原标题:国防部新闻发言人谭克非就美对台军售答记者问问:据报道,美国国防部发布消息称,美国务院已批准总价约11亿美元的对台军售,包括导弹及监视雷达项目等。请问对此有何……63岁丁勇岱近照曝光,身材发福大肚腩,和妈妈五官相似复制粘贴 老戏骨丁勇岱推着年迈母亲出门闲逛的视频曝光,画面很温馨,母慈子孝。从视频中看,当天阳光晴朗,丁勇岱和老母亲出门呼吸新鲜空气,欣赏路旁的美景。丁母年纪很大了,行动不方便,出……任贤齐《诛仙》直播玩梗,一句挽留的话,尽显高情商热议聚热点网 “我回来会带着一身光彩你还在一辈子我相伴”,任贤齐昨晚在直播中弹着吉他,清唱《诛仙我回来》的回忆杀画面,感动了无数《诛仙》手游玩家。不过,因为《诛仙》手游的高清重制版刚刚……骆驼祥子作者简介和内容简要是什么(骆驼祥子作者简介和内容简要 《骆驼祥子》【作者简介】老舍,原名舒庆春,字舍予,中国现代著名小说家、戏剧家,被誉为人民艺术家。代表作有小说《骆驼祥子》《四世同堂》,话剧《龙须沟》《茶馆》等。【内……前天晚上一场脱口秀,又在A股里种了一茬韭菜热闻聚热点网 中秋这两天,大家纷纷去各个网红景点打卡。但是万万没想到,最火的打卡纪念地不是某个旅游胜地,竟然是脱口秀概念股。原来,在最新一期的《脱口秀大会第五季》上,脱口秀演员H……NBA历史75大球星巡礼,艾弗森,他人用一生铸辉煌,我用一场 艾弗森可能是比乔丹和科比对中国球迷影响更为深远的超级巨星,我们没有赶上神的时代,当中国球迷刚开始看NBA的时候,艾弗森正书写着属于自己的孤胆神话。以一己之力硬杠所向披靡的……金猫榜悬疑剧《你安全吗》今晚开播,7位实力派联手助阵,有爆款 “抓小偷啊!”“啦,啦啦啦啦,啦啦啦啦啦。。。。。。”歌声响起的一刻,一个欢快有趣的故事呼之欲出。荣梓杉挎着工具包,在小巷中奋力逃跑,身后是一群紧追不放的大妈,边追……《海贼王》新剧场版国内定档:中文配音!热评聚热点网 《海贼王》2016年最新剧场版动画《海贼王剧场版13:GOLD》,已经在日本上映了,本次的剧场版在日本的票房成绩也是相当的不错,有望超过50亿日元。之前《海贼王剧场版13:GO……买了个高仿手表后悔了?高仿手表值得买吗?玩表其实很烧脑,来解 表中的暗号知多少?百达翡丽5178的盘面6点钟方向的“EMAIL”到底是什么意思,是手表可以接收邮件吗?事实上,竟是珐琅盘的英文字印错了,将“enamel”印成了“EMAIL”……市场上酱酒品类众多,价格差异甚大,我们该如何区分酱酒的优劣呢 酒文化渊源流长,如今白酒跟我们社会生活的发展密不可分。前些年大家都在追捧浓香酒,而浓香型白酒也成为喝的人最多的香型白酒。如今大家转而去追捧酱香酒,酱酒也因此有了很好的发展。……
太阳或曾有“孪生兄弟”,第九大行星与它有关热评聚热点网 没有借条起诉还钱期限是多久热闻聚热点网 医疗事故精神损害抚慰金的赔偿标准热闻聚热点网 借条上只有指纹没有签字生效吗?热闻聚热点网 打架轻伤赔偿包括哪些费用热议聚热点网 公司破产后债务谁承担?热评聚热点网 外国人是否可以在中国领结婚证热评聚热点网 【歌词】BoysBoysBoys歌手:LadyGaGa热议聚 结婚登记手续有哪些特殊情况热文聚热点网 2021年最新浙江省防汛防台抗旱条例修订热评聚热点网 缺席判决的法院会怎么判热博聚热点网 无效婚姻如何重办结婚证?热博聚热点网
爱与恨个人合同山顶22!泰山景区发布做好寒潮防范提示热议聚热点网 与杭州三釜服饰有限公司签约做主播不挣钱反而要赔万血压有点高,会有啥表现?别人能看出来吗?。。。龙源电力登陆A股,跌破发行价盘中停牌教育孩子,纠正孩子的坏毛病,刀子嘴,豆腐心不能要德妃紫苏防晒防晒黑吗德妃紫苏防晒使用感在历史记载中,商纣王为什么要剜比干的心?宝宝洗澡太频繁好吗?妈妈们看过来!GitCommitLog提交规范彩叶草怎么过冬,光照控温入冬修剪养护

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找新乡渭南铜川松江山南雅安松原荃湾淮北昭通平凉鞍山赤峰苗栗保亭池州渝北株洲陇南濮阳三沙秀山密云鸡西