为什么需要多个shared_future对象来同步数据

2023-12-20

指向数据结构的指针通过以下方式与多个线程共享std::promise and std::shared_future。 从书中'C++ 并发实践' 作者:Anthony Williams(第 85-86 页),似乎只有当每个接收线程使用副本时,数据才会正确同步 的std::shared_future对象而不是每个线程访问单个全局对象std::shared_future.

为了说明这一点,考虑一个线程创建bigdata并将指针传递给具有只读访问权限的多个线程。 如果线程之间的数据同步处理不正确,内存重新排序可能会导致未定义的行为(例如,worker_thread读取不完整的数据)。

这个(不正确?)实现使用单个全局std::shared_future:

#include <future>

struct bigdata { ... };

std::shared_future<bigdata *> global_sf;

void worker_thread()
{
    const bigdata *ptr = global_sf.get();
    ...  // ptr read-only access
}

int main()
{
    std::promise<bigdata *> pr;
    global_sf = pr.get_future().share();

    std::thread t1{worker_thread};
    std::thread t2{worker_thread};

    pr.set_value(new bigdata);
    ...
}

在这个(正确的)实现中,每个worker_thread得到一份副本std::shared_future:

void worker_thread(std::shared_future<bigdata *> sf)
{
    const bigdata *ptr = sf.get();
    ...
}

int main()
{
    std::promise<bigdata *> pr;
    auto sf = pr.get_future().share();

    std::thread t1{worker_thread, sf};
    std::thread t2{worker_thread, sf};

    pr.set_value(new bigdata);
    ....

我想知道为什么第一个版本不正确。

If std::shared_future::get()是一个非常量成员函数,它是有意义的,因为访问单个std::shared_future来自多个线程的数据竞争本身就是一场数据竞争。 但由于这个成员函数被声明为 const,并且global_sf对象与线程同步,从多个线程并发访问是安全的。

我的问题是,为什么只有在每个worker_thread收到一份副本std::shared_future ?


您的实施使用单一的全局shared_future完全没问题,如果有点不寻常的话,这本书似乎是错误的。

[futures.shared_future] ¶2

[ Note:成员函数shared_future不与自身同步,但与共享状态同步。 —end note ]

注释是非规范性的,因此以上内容是多余地明确了规范性措辞中已经隐含的事实。

[种族简介] ¶2

两个表达式求值conflict如果其中一个修改内存位置,而另一个读取或修改同一内存位置。

¶6

某些库调用同步于由另一个线程执行的其他库调用。

[...附加段落定义发生在之前就同​​步而言...]

¶19

两个动作是潜在并发如果它们由不同的线程执行...程序的执行包含一个数据竞赛如果它包含两个潜在并发冲突的操作,至少其中一个不是原子的,并且两者都发生在另一个之前......

[关于数据竞赛的解析] ¶3

C++ 标准库函数不得直接或间接修改当前线程以外的线程可访问的对象,除非这些对象是通过函数的非常量参数直接或间接访问的,包括this.

所以我们知道调用global_sf.get()不同线程中的线程可能是并发的,除非您为它们提供额外的同步(例如互斥体)。但我们也知道这需要global_sf.get()在不同的线程中不会冲突,因为它是一个const方法,因此禁止修改可从多个线程访问的对象,包括*this。因此,不满足数据争用(无序的、可能并发的冲突操作)的定义,程序不包含数据争用。

无论如何,人们通常希望避免全局变量,但这是一个单独的问题。

请注意,如果这本书是正确的,那么它就会包含矛盾。它声称的代码是正确的仍然包含全局shared_future当多个线程创建本地副本时,可以从多个线程访问它:

void worker_thread()
{
    auto local_sf = global_sf; // <-- unsynchronized access of global_sf here

    const bigdata *ptr = local_sf.get();
    ...
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么需要多个shared_future对象来同步数据 的相关文章

  • 临时表是线程安全的吗?

    我正在使用 SQL Server 2000 它的许多存储过程广泛使用临时表 数据库的流量很大 我担心创建和删除临时表的线程安全性 假设我有一个存储过程 它创建了一些临时表 它甚至可以将临时表连接到其他临时表等 并且还可以说两个用户同时执行存
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • IO 密集型任务中的 Python 多线程

    建议仅在 IO 密集型任务中使用 Python 多线程 因为 Python 有一个全局解释器锁 GIL 只允许一个线程持有 Python 解释器的控制权 然而 多线程对于 IO 密集型操作有意义吗 https stackoverflow c
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查

随机推荐

  • 将单个文件卷安装为 Docker 中的目录

    Docker 文档 http docs docker com engine userguide dockervolumes mount a host file as a data volume说可以将单个文件挂载到 Docker 容器中 v
  • 玩! 2.0 Scala - 访问全局对象

    我已经声明了一个在应用程序启动时实例化的对象 我想在控制器内访问它 这是插件的一部分 我希望能够使用该插件 但我似乎无法通过第一部分 找到MyWebsocketConnection目的 没有一个示例显示如何执行此操作 我不想注入控制器 因为
  • 如何修复 Prisma Client 自定义模型未定义的问题

    我生成了一个项目打字稿快速启动器 https www npmjs com package typescript express starter并选择了Prisma https www prisma io 作为 ORM 启动项目生成的基本 用
  • python:对我的复制变量的更改会影响原始变量[重复]

    这个问题在这里已经有答案了 我有一个列表 我创建了一个副本 以便在保留原始列表的同时进行一些操作 然而 当我设置copy list等于org list 它们会变成同样的东西 如果我改变copy list org list也发生变化 例如 o
  • Flutter 视频播放器无法在 ios 中播放

    我正在使用 video player 包在 flutter 中播放网络视频 在安卓上运行良好 但在ios上无法加载 颤振3 3 3 视频播放器 2 4 7 PS 服务器调用是https 问题发生在真实设备和响应头有接受范围 字节 Reque
  • 无法在 MySQL 5.7 中添加外键(引用表中缺少约束)

    我正在尝试运行外键添加查询 如下所示 外键检查设置为 0 两个表中的列完全相同 此外 两者都是主键 这里的解决方案都没有帮助解决这个问题 我在本地主机上 mysql gt alter table deliveryaddress gt add
  • 如何从 b 树中删除元素?

    我正在尝试了解 b 树 我能找到的每个来源似乎都忽略了有关如何从树中删除元素同时保留 b 树属性的讨论 有人可以解释该算法或向我指出可以解释其工作原理的资源吗 维基百科页面上有对此的解释 B 树 删除 http en wikipedia o
  • 在发生未处理的异常后,我可以将执行返回到失败的方法吗?

    我有一个 ASP NET 网站 其中包含一些 WCF 服务 我已连接到 Application Error 事件 因此可以记录任何未处理的异常 我真正想做的是将执行传递回被调用的方法 这样我就可以向客户端返回一些有意义的内容 而不是抛出Fa
  • 将按结果分组保存到单独的 CSV 文件中

    我有一个代码 用于使用 CSV 数据创建组并使用该组创建新文件 我读取了 csv 文件 然后使用它 问题是当我的函数工作并使用数据创建新文件时 新文件的名称是组的名称 我不希望这样 ID Inventory Domain Requests
  • Android从缩略图获取图像路径?

    我正在尝试为目前市场上的我的应用程序提供关键更新 我需要查询 MediaStore 中的缩略图 并将缩略图加载到 GridView 中 到目前为止一切顺利 现在我只需要根据我所拥有的内容 即缩略图的路径 获取用户外部存储上实际全尺寸图像的路
  • Oracle复制数据到另一个表

    在Oracle中 我将数据从备份复制到新表 但不起作用 正确的语法是什么 Thanks select CODE MESSAGE into EXCEPTION CODES CODE MESSAGE from Exception code tm
  • 为什么 sizeof(std::mutex)==40 (gcc,clang,icc)? [复制]

    这个问题在这里已经有答案了 而不是sizeof std atomic
  • 使用 SvelteKit 将图像放置在哪里

    我已经使用 Svelte 一段时间了 现在我已切换到 SvelteKit 这样我就可以添加多个页面 我想向我的网站添加一些图像 但我不知道将它们放在哪里 在 Svelte 中我会把它们放进去public images但没有public带有
  • 在 Android 上的 AAC 流中查找

    我从 HTTP 服务器获取 AAC 流并将其用作MediaPlayer在安卓中 它运行得很好 但是当我尝试执行时mediaPlayer seekTo int position 我收到以下错误大约一百万次 WARN AACDecoder 13
  • 处理 PowerShell 脚本中的命令提示符错误

    我正在尝试运行一些命令提示符命令 例如schtasks在 PowerShell 脚本中 我想知道如何处理 PowerShell 中命令引发的错误 I tried cmd exe c schtasks Query TN xx echo ERR
  • System.Messaging - 为什么 MessageQueue 不提供 Send 的异步版本

    有人知道为什么 System Messaging 不提供异步版本的 Send 方法来将 MSMQ 消息发送到队列 实际上有 Peek 和 Receive 方法的异步版本 通过可以转换为 C 5 异步等待方法的 Begin End 对 但令人
  • 初始化一个sqlite数据库android

    大家好 我对 Android 开发还很陌生 我想向我的应用程序添加一个数据库 问题是我不知道如何仅初始化整个表一次 我读了很多书 发现你可以做到 的压倒性作用onCreate SQLiteDatabase db 辅助类中的方法 这些是我的数
  • 全局 Jest SpyOn 函数不调用原始函数

    我希望有人能帮助我理解 js 原型的交互性和jest spOn 我有一个小例子 文件中的示例类TestObj ts export default class TestObj foo Do Something e g console log
  • iOS 7 模拟器日语键盘词典位于哪里?

    这个问题和这个有点相似 如何在 iPhone 模拟器上启用日语键盘 https stackoverflow com questions 8051141 how do i enable the japanese keyboard on the
  • 为什么需要多个shared_future对象来同步数据

    指向数据结构的指针通过以下方式与多个线程共享std promise and std shared future 从书中 C 并发实践 作者 Anthony Williams 第 85 86 页 似乎只有当每个接收线程使用副本时 数据才会正确