分叉的 IORef 读取器函数似乎会停止主线程

2023-12-26

我正在对并发性和内存可见性进行一些实验,并遇到了这种奇怪的行为(请参阅内联评论):

module Main
    where

import Data.IORef
import Control.Concurrent
import System.CPUTime

import System.IO

main = do
    hSetBuffering stdout NoBuffering

    r <- newIORef False
    putStrLn "forking..."  -- PRINTED
    forkIO $ f r
    threadDelay 1000000

    putStrLn "writeIORef"  -- NEVER PRINTED
    writeIORef r True

    threadDelay maxBound

f :: IORef Bool -> IO ()
f r = readIORef r >>= \b-> if b then print "NEVER PRINTED" else f r

我期待着也许writeIORef对子线程不可见,但主线程不会简单地(显然)停止。

在 ghc 7.8.3 上编译

 cabal exec ghc -- --make -fforce-recomp -O2 -threaded visibility.hs  

并运行

./visibility +RTS -N

这里发生了什么事?

EDIT:所以我的机器有两个真正的核心和两个超线程核心,所以+RTS -NGHC 有 4 项功能。根据 Gabriel Gonzalez 的回答,我尝试了以下操作,看看调度程序是否将两个线程放在同一个物理处理器上:

module Main
    where

import Data.IORef
import Control.Concurrent    
import GHC.Conc(threadCapability,myThreadId,forkOn)

main = do    
    r <- newIORef False
    putStrLn "going..."

    (cap,_) <- threadCapability =<< myThreadId
    forkOn (cap+1) $ f r                    -- TRIED cap+1, +2, +3....
    threadDelay 1000000

    putStrLn "writeIORef"                   -- BUT THIS STILL NEVER RUNS
    writeIORef r True

    threadDelay maxBound

f :: IORef Bool -> IO ()
f r = readIORef r >>= \b-> if b then print "A" else f r

ghc仅在明确定义的安全点(仅在分配内存时)挂起线程。我相信您的分叉线程永远不会分配内存,因此它永远不会放弃对其他线程的控制。因此,一旦编译器安排了分叉线程(有时在您的程序的中间),您的主线程就永远不会继续进行。threadDelay).

您可以了解更多有关安全点的信息here http://www.aosabook.org/en/ghc.html在“轻量级线程和并行性”部分中。

编辑:正如托马斯提到的,你可以使用Control.Concurrent.yield当您遇到此类情况时,明确放弃控制权。

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

分叉的 IORef 读取器函数似乎会停止主线程 的相关文章

  • 将系统命令的结果绑定到 Haskell 中的变量

    如何在 Haskell 中运行系统命令and将其结果 即标准输出 绑定到变量 在伪 Haskell 中 我正在寻找类似以下内容的内容 import System Process main do output lt callCommand e
  • 为什么 Haskell 中有协函子和逆变函子的区别,而范畴论却没有区别?

    这个答案是从范畴论的角度来看的 https math stackexchange com a 661989 72174包括以下语句 事实是 协函子和逆变函子之间没有真正的区别 因为每个函子只是一个协变函子 More in details a
  • ErrorT 已弃用,但 exceptT 不适合

    我有一个一元计算 在某些时候 由于单子模式匹配 它开始需要 MonadFail 约束 我的简单解决方法是使用以下命令运行它 fmap either error id runErrorT 然而哎呀 Deprecated Use Control
  • 如何让 Show 显示函数名称?

    作为一个让我熟悉 Haskell 的简单练习 在 Youtube 上闲逛并偶然进入美国倒计时游戏节目之后 我想为数字游戏制作一个求解器 你得到 6 个数字 需要将它们与 为了得到给定的结果 到目前为止我所得到的是非常脑死亡的 let ope
  • 如何从 haskell 中的 IOError 获取 errno?

    我在 haskell 平台上 GHC 6 12 1 作为 apt get 安装在 Debian Squeeze 上 鉴于我需要在与最初引发它的线程不同的线程上使用它 如何从 IOError 中获取底层 errno 我需要这个的原因是因为我正
  • 独占锁定ConcurrentHashMap

    我知道不可能锁定 ConcurrentHashMap 进行独占访问 但是 我找不到原因 是因为构成CHM的 Segment 没有被api公开吗 据推测 如果是的话 客户端代码可以执行 交接 锁定 Cheers 我知道不可能锁定 Concur
  • 在 Haskell 中计算移动平均线

    我正在学习 Haskell 所以我尝试实现移动平均函数 这是我的代码 mAverage Int gt Int gt Float mAverage x a fromIntegral k fromIntegral x k lt rawAvera
  • Haskell 下划线与显式变量

    我已经学习 Haskell 几个星期了 我有一个关于下划线的使用的问题 作为函数参数 我认为用一个具体的例子来问我的问题会更好 假设我想定义一个函数 根据提供的索引提取列表的元素 是的 我意识到 已经是预先定义的 我可以定义该函数的两种方法
  • 并发:C++11 内存模型中的原子性和易失性

    全局变量在 2 个不同内核上的 2 个并发运行的线程之间共享 线程对变量进行写入和读取 对于原子变量 一个线程可以读取过时的值吗 每个核心可能在其缓存中具有共享变量的值 并且当一个线程写入缓存中的其副本时 不同核心上的另一个线程可能会从其自
  • 插入并发问题-多线程环境

    我有一个问题 即使用完全相同的参数在完全相同的时间调用相同的存储过程 存储过程的目的是获取记录 如果存在 或创建并获取记录 如果不存在 问题是两个线程都在检查记录是否存在并报告错误 然后都插入新记录 在数据库中创建重复记录 我尝试将操作保留
  • 将 num 的签名键入 double?

    我才刚刚开始为你学习 Haskell 以获得伟大的好处 并且我在类型类方面遇到了一些麻烦 我想创建一个接受任何数字类型并强制其为双精度的函数 我的第一个想法是定义 numToDouble Num gt Double 但我认为这不起作用 因为
  • Java 执行器和长寿命线程

    我继承了一些使用 Executors newFixedThreadPool 4 的代码运行 4 个长寿命线程来完成应用程序的所有工作 这是推荐的吗 我读过Java 并发实践 https rads stackoverflow com amzn
  • 如何在 Haskell 中安装库?

    我尝试使用控制 Monad Extra andM https hackage haskell org package extra 1 7 10 docs Control Monad Extra html import Control Mon
  • 如何在 Haskell 中制作打勾游戏的图案?

    实现有 2 个参数的函数 ticktick 第一个参数是自然数元组 定义游戏场地的行数和列数 第二个列表包含由玩家 x 和玩家 o 轮流玩的坐标给出的井字游戏比赛的记录 打印游戏的实际状态 其中游戏区域将由字符 和 界定 空方块 以及字符
  • Haskell:Data.Numbers.Primes 库在哪里?

    我尝试导入 Data Numbers Primes import Data Numbers Primes 伦哈斯克尔给了我 5 hs 1 8 Could not find module Data Numbers Primes Use v t
  • QuickCheck是否可以生成任意函数

    我试图为身份编写一个 QuickCheck 测试 f y f y 我最初的计划是编写一个返回函数和整数的任意生成器 具有签名Gen Int gt Int Int 并在prop DollerDoesNothing使用 不使用测试该功能应用程序
  • 如何在haskell中获取变量名称

    我来到 haskell 时有一些 c 背景知识 想知道是否有类似的 define print a printf s d n a a int a 5 print a 应该打印 a 5 这是 augustss 提到的 TH 解决方案 LANGU
  • Laravel - 停止并发访问记录

    在 Laravel 中 有什么方法可以停止同时与同一条记录交互 例如 如果用户 A 正在编辑一条记录 那么我同时需要阻止用户 B 编辑同一条记录 注意 我在 Laravel 5 2 中使用 SESSION DRIVER file 目前大约有
  • 找不到模块“Yesod”

    我有以下代码 LANGUAGE TypeFamilies QuasiQuotes MultiParamTypeClasses TemplateHaskell OverloadedStrings module Simple where imp
  • Haskell 输入返回元组

    我想知道 IO 函数是否可以返回元组 因为我想从这个函数中获取这些元组作为另一个函数的输入 investinput IO gt Char Int investinput do putStrLn Enter Username username

随机推荐

  • 如何将函子分配给函数指针?

    一般来说 我可以将函数对象分配给函数指针吗 我想做这样的事情 include
  • 将项目从 Delphi 3 移至 Delphi 2010

    我被要求重新打开一个我在 1998 99 年用 Delphi 3 编写的项目 此后该项目一直稳定运行 我在一台老化的 Windows 98 机器上有 Delphi 3 代码库 它的存在只是为了让这个项目保持活力 显然 我想在进行任何重大修改
  • 如何在 PostgreSQL 中获取数组的最后一个元素?

    The 关于数组的 PostgreSQL 文档 http www postgresql org docs 9 2 static arrays html提供了一个使用示例 1 访问数组的最后一个元素 然而虽然SELECT arr 2 3 产生
  • Notepad++ 查找文件名

    在Notepad 中 我有时需要打开存在于不同文件夹中的文件 这需要时间才能转到文件夹 并通过Light Explorer搜索文件 Notepad 有什么功能或插件可以让我直接打开文件吗 假设 如果我需要打开一个名为 notepad php
  • 检查元素是否包含#shadow-root

    是否可以查看 Shadow DOM 元素是否存在 我不太关心操纵它 甚至不是真正针对它 我理解封装的原因 但我希望能够根据 Shadow DOM 元素是否存在来设置常规 DOM 中其他元素的样式 有点像 if element id shad
  • Win32/MFC 从客户端矩形获取窗口矩形

    我知道有一个函数可以接受客户端矩形 并将其转换为窗口矩形 我只是找不到 记住它 有谁知道它是什么 它会做类似的事情 const CRect client 0 0 200 200 const CRect window ClientRectTo
  • 插件“FEDERATED”已禁用

    我尝试使用 easyPHP 启动 MySQL 响应是日志文件的警报窗口 主要错误是 通过网上研究 我发现解决方案是将联合选项添加到my ini文件 我这样做了 但它仍然不起作用 以下是日志文件的摘录 以了解更多信息 2013 05 03 1
  • 获取点击元素的ID

    div div div div 尝试此方法来获取单击的元素的 ID 并发出警报 我确信这是我所缺少的一些非常基本的东西 有人可以帮忙吗 这实际上非常基本 停止使用内联事件处理程序
  • 每次尝试以特定顺序循环 3 个线程

    我的问题是如何让一个线程运行 然后再运行一次 然后再次运行 然后它会重复本身 我有一个主文件 private static ThreadManager threadManager public static void main String
  • 通用选择不适用于位类型

    基于这个答案 https stackoverflow com a 18469483 1993545 我尝试为我的桌子创建一个选择 ALTER PROCEDURE Einrichtung Select Parameters with defa
  • 如何在 Jetpack Compose 中向图标添加阴影/边框/高度

    我想在 Jetpack compose 中为我的图标添加阴影 以便图像和文本具有 大致 相似的阴影 Text text HAS SHADOW style MaterialTheme typography body2 copy shadow
  • 打印汉字的ESC/POS命令

    打印机型号 爱普生TM T88V ESC POS命令指南 见P 115 http download delfi com SupportDL Epson Manuals TM T88IV Programming 20manual 20APG
  • 是否需要将原始类型键入枚举?

    我正在浏览NSString查看头文件 看看 Apple 如何编写枚举 并发现了这段代码 enum NSStringEncodingConversionAllowLossy 1 NSStringEncodingConversionExtern
  • Google DataFlow/Python:save_main_session 和 __main__ 中的自定义模块导入错误

    有人可以澄清使用时的预期行为吗save main session和导入的自定义模块 main 我的 DataFlow 管道导入 2 个非标准模块 一个通过requirements txt另一个通过setup file 除非我将导入移至使用它
  • 从txt中解析IP地址

    我正在尝试下载一个txt您可以找到的文件here http proxy ip list com download free proxy list txt 下载文件不是问题 testfile urllib URLopener testfile
  • 创建数组的副本并操作原始数组

    首先我要为我糟糕的英语道歉 我会尽力说得清楚 我有一个 3 维数组 只是一个 2 维数组的数组 我的目标是获取其中一个二维数组 并将其逆时针旋转 90 它看起来像这样 1 2 3 4 5 6 7 8 9 我尝试让它像这样 旋转 3 6 9
  • 发生类型错误:超出翻译容量

    当我运行我的示例时 出现以下类型错误 Translation capacity exceeded In this scope universe contains 21 atoms and relations of arity 8 canno
  • 未捕获的 RangeError:超出了最大调用堆栈大小,JavaScript

    我有个问题 open function type Some code document getElementById type addEventListener click l close type false close function
  • 写入开始后无法设置此属性!在 C# WebRequest 对象上

    我想重用 WebRequest 对象 以便保存 cookie 和会话以供以后向服务器请求 下面是我的代码 如果我第二次使用 Post 函数两次 request ContentLength byteArray Length 它会抛出异常 写入
  • 分叉的 IORef 读取器函数似乎会停止主线程

    我正在对并发性和内存可见性进行一些实验 并遇到了这种奇怪的行为 请参阅内联评论 module Main where import Data IORef import Control Concurrent import System CPUT