Skip to content

搞英语 → 看世界

翻译英文优质信息和名人推特

Menu
  • 首页
  • 作者列表
  • 独立博客
  • 专业媒体
  • 名人推特
  • 邮件列表
  • 关于本站
Menu

线程安全的内存复制

Posted on 2025-02-08

图片-12-825x510.jpg

软件中的常见操作是复制内存块。在C/C++中,我们经常调用函数memcpy来达到这个目的。

但是,如果在复制数据时另一个线程正在修改源或目标,会发生什么情况?结果从根本上是不可预测的,并且几乎肯定是编程错误。

既然复制函数是错误的,为什么要以这种方式编写它呢?假设您正在用 C++ 实现 JavaScript 引擎,例如 Google v8。在 JavaScript 中,我们有 SharedArrayBuffer 实例,可以从不同的线程修改和复制它们。作为开发 JavaScript 引擎的工程师,您无法始终阻止用户编写有错误的代码。

无论如何,您都会遇到数据竞争:两个或多个线程同时访问同一内存位置,其中至少有一个访问是写入操作,而没有同步机制来确保这些操作按特定顺序发生。

会发生什么? C++ 标准规定数据竞争会导致未定义的行为。实际上,C++ 语言不会告诉您会发生什么。可能会发生崩溃。当然,JavaScript 工程师不愿意看到崩溃。

重要的是,“未定义的行为”也不会告诉您一定存在错误。实际上,它告诉您作为程序员,您有额外的责任来确保代码是安全的。编程语言本身不提供任何保证。

为什么像 C 和 C++ 这样的语言会留下未定义的行为?

一个很好的比喻是一个拥有许多子组件的组织,可以随时添加新的子组件。想象一下行星的星际联邦。星际联邦可以指定明确定义的总体法律,但仍会存在特定于您居住的星球的剩余极端情况。

这就是 C 和 C++ 的精神:这些编程语言可以针对非常广泛的平台。对于其中一些平台来说,数据竞争不会产生任何后果……而对于其他平台来说,数据竞争可能会带来很大的问题或只是速度缓慢。此外,通过不指定行为,它允许编译器设计者进行一些选择。因此,编程语言将其留给您来检查。

考虑一个冲突的内存复制,例如,您从数组 A 复制到数组 B,而另一个线程从数组 B 复制到数组 A。在大多数平台下,这不会导致崩溃或任何特别危险的情况。在最坏的情况下,您的数组中可能会出现垃圾数据。

但如果您使用自动清理工具,您仍然可能会收到有关数据争用的警告,即使它无关紧要。您可以通过告诉工具您已检查副本是否安全来消除警告。

相反,您可以滚动自己的“安全”内存副本,以原子方式逐字节加载内容(例如)。 C++20 中可能的解决方案如下所示:

 void safe_memcpy ( char * dest , const char * src , size_t count ) {   for ( size_t i = 0 ; i <计数; + + i ) {   字符输入=   std :: atomic_ref < const char > ( src [ i ] )   。加载( std :: memory_order_relaxed ) ;   std :: atomic_ref < char > ( dest [ i ] )   。存储(输入, std :: memory_order_relaxed ) ;   }   }

我们现在已经废除了任何类型的未定义行为。代码应该是完全“安全”的,不再有数据竞争。

那么为什么不总是使用这种安全的方法呢?

因为它可能比传统内存复制慢 40 倍。

这成为一个工程问题。有时候,性能确实并不重要。

在编程中,几乎没有免费的午餐。你通常会做出选择:追求高绩效但承担更多责任,或者牺牲绩效以减少后顾之忧。

原文: https://lemire.me/blog/2025/02/07/thread-safe-memory-copy/

本站文章系自动翻译,站长会周期检查,如果有不当内容,请点此留言,非常感谢。
  • Abhinav
  • Abigail Pain
  • Adam Fortuna
  • Alberto Gallego
  • Alex Wlchan
  • Answer.AI
  • Arne Bahlo
  • Ben Carlson
  • Ben Kuhn
  • Bert Hubert
  • Bits about Money
  • Brian Krebs
  • ByteByteGo
  • Chip Huyen
  • Chips and Cheese
  • Christopher Butler
  • Colin Percival
  • Cool Infographics
  • Dan Sinker
  • David Walsh
  • Dmitry Dolzhenko
  • Dustin Curtis
  • Elad Gil
  • Ellie Huxtable
  • Ethan Marcotte
  • Exponential View
  • FAIL Blog
  • Founder Weekly
  • Geoffrey Huntley
  • Geoffrey Litt
  • Greg Mankiw
  • Henrique Dias
  • Hypercritical
  • IEEE Spectrum
  • Investment Talk
  • Jaz
  • Jeff Geerling
  • Jonas Hietala
  • Josh Comeau
  • Lenny Rachitsky
  • Liz Danzico
  • Lou Plummer
  • Luke Wroblewski
  • Matt Baer
  • Matt Stoller
  • Matthias Endler
  • Mert Bulan
  • Mostly metrics
  • News Letter
  • NextDraft
  • Non_Interactive
  • Not Boring
  • One Useful Thing
  • Phil Eaton
  • Product Market Fit
  • Readwise
  • ReedyBear
  • Robert Heaton
  • Ruben Schade
  • Sage Economics
  • Sam Altman
  • Sam Rose
  • selfh.st
  • Shtetl-Optimized
  • Simon schreibt
  • Slashdot
  • Small Good Things
  • Taylor Troesh
  • Telegram Blog
  • The Macro Compass
  • The Pomp Letter
  • thesephist
  • Thinking Deep & Wide
  • Tim Kellogg
  • Understanding AI
  • 英文媒体
  • 英文推特
  • 英文独立博客
©2025 搞英语 → 看世界 | Design: Newspaperly WordPress Theme