You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell中mask/restore作用验证:如何修改测试代码显化差异

Haskell中bracket的mask机制差异测试方法

你当前的测试没体现出mask的作用,是因为mask的核心是阻止异步异常中断被包裹的代码段——标准库的bracket用mask保护了资源获取(acquire)和释放(release)的过程,而你的myBracket没有这个保护。要显化差异,需要在acquire或release的执行过程中发送异步异常,而非等work阶段或流程后期发异常。

测试前置代码

先定义通用的异常、acquire、release和work函数:

import Control.Concurrent
import Control.Exception
import Control.Monad

data MyException = MyException deriving (Show, Exception)

-- 带有延迟的资源获取,方便在执行过程中发送异常
acquire :: IO ()
acquire = do
  putStrLn "Starting acquire"
  threadDelay 1000000  -- 延迟1秒
  putStrLn "Acquire done"

-- 带有延迟的资源释放
release :: () -> IO ()
release _ = do
  putStrLn "Starting release"
  threadDelay 1000000
  putStrLn "Release done"

work :: () -> IO ()
work _ = putStrLn "Working..."

场景1:在acquire执行期间发送异步异常

测试标准库bracket

main :: IO ()
main = do
  tid <- forkIO $ bracket acquire release work
  threadDelay 500000  -- 等待500ms,此时acquire仍在执行
  throwTo tid MyException
  threadDelay 2000000  -- 等待流程结束

输出结果:

Starting acquire
Acquire done
Starting release
Release done

原因:mask保护了acquire的执行,即使收到异步异常,也会先完成资源获取,再执行release释放资源,最后响应异常。

测试自定义myBracket

main :: IO ()
main = do
  tid <- forkIO $ myBracket acquire release work
  threadDelay 500000
  throwTo tid MyException
  threadDelay 2000000

输出结果:

Starting acquire

原因:没有mask保护,acquire执行到一半时被异步异常中断,后续的release完全不会执行,资源泄露。

场景2:在release执行期间发送异步异常

测试标准库bracket

main :: IO ()
main = do
  tid <- forkIO $ bracket acquire release work
  threadDelay 1500000  -- 等待acquire和work完成,release开始执行
  throwTo tid MyException
  threadDelay 2000000

输出结果:

Starting acquire
Acquire done
Working...
Starting release
Release done

原因:mask保护了release的执行,异步异常不会中断资源释放流程。

测试自定义myBracket

main :: IO ()
main = do
  tid <- forkIO $ myBracket acquire release work
  threadDelay 1500000
  throwTo tid MyException
  threadDelay 2000000

输出结果:

Starting acquire
Acquire done
Working...
Starting release

原因:release执行到一半被异步异常中断,资源未完全释放。

核心差异总结

标准库bracket的mask将整个资源生命周期包裹,仅在restore (thing a)(即业务逻辑work)阶段允许异步异常中断;而你的myBracket没有这个保护,资源获取和释放的过程都可能被异步异常打断,这会导致资源泄露或释放不彻底。

内容的提问来源于stack exchange,提问作者WHITECOLOR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 15:10:16