需要击败 GC 并在对象超出范围后将其销毁

2024-01-17

我有几段代码需要用互斥锁来保护。问题是代码看起来像这样:

lock(mylockobject) {
  if(!foo())
    throw new MyException("foo failed");
  if(!bar())
    throw new MyException("bar failed");
}

使用锁,它可以按我想要的方式工作,但现在我需要使用互斥体。这里明显的问题是,如果我获取互斥体并且 foo() 或 bar() 失败,我必须在抛出每个异常之前显式释放互斥体。

在 C++ 中,我将利用在堆栈上创建的对象的范围,并将互斥锁锁定在对象的构造函数中,然后在析构函数中释放它。对于 .NET 的垃圾收集,我认为这行不通。我编写了一个测试应用程序并确认如果我执行以下操作:

public class AutoMutex
{
  private Mutex _mutex;
  public AutoMutex(Mutex mutex)
  {
     _mutex = mutex;
     _mutex.WaitOne();
  }

  ~AutoMutex()
  {
    _mutex.ReleaseMutex();
  }
}

然后有这样的代码:

// some code here...
Mutex my_mutex = new Mutex(false, "MyMutex");
{ // scoping like I would do in C++
  AutoMutex test = new AutoMutex(my_mutex);
  test = null;
}

析构函数(终结器?)直到很久以后才会被调用。

谷歌还没有给我指明正确的方向,但我仍在努力......请让我知道你如何解决这个小问题,如果可能的话。


几点。

1)您要搜索的是“一次性模式”。执行时要非常小心正确地。当然,互斥体already实现了一次性模式,所以我不清楚为什么你想要自己制作,但仍然值得学习。

请参阅此问题,了解有关像 RAII 一样使用一次性模式是否明智的一些其他想法:

使用 IDisposable 和“使用”作为获取“范围行为”以实现异常安全的手段是否滥用? https://stackoverflow.com/questions/2101524

2)Try-finally也有你想要的语义。当然,“using”块只是 try-finally 的语法糖。

3) 你是吗sure当有东西抛出时你想释放互斥体吗?您确定要扔进保护区吗?

由于以下原因,这是一种不好的代码味道。

首先为什么要有互斥体?通常是因为模式是这样的:

  • 状态一致但陈旧
  • 锁定对状态的访问
  • 使状态不一致
  • 使状态一致
  • 解锁对国家的访问
  • 状态现在一致且新鲜

考虑一下在“使状态一致”之前抛出异常时会发生什么。您解锁了对状态的访问,该状态现在不一致且陈旧.

这可能是一个更好的主意保持锁定。是的,这意味着存在死锁的风险,但至少你的程序不会在垃圾、陈旧、不一致的状态下运行。

从锁保护区域内抛出异常是一件非常非常可怕的事情,您应该尽可能避免这样做。从锁内部抛出的异常使您必须在两种可怕的事情之间做出选择:要么陷入死锁,要么当程序操作不一致的状态时出现疯狂的崩溃和不可重现的行为。

您真正应该实现的模式是:

  • 状态一致但陈旧
  • 锁定对状态的访问
  • 使状态不一致
  • 使状态一致
  • 如果发生异常,则回滚到陈旧的一致状态
  • 解锁对国家的访问
  • 状态现在是一致的,如果没有例外,状态是新鲜的

这是更安全的选择,但是编写执行此类事务的代码很困难。没有人说多线程很容易。

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

需要击败 GC 并在对象超出范围后将其销毁 的相关文章

  • 使用链表进行堆排序

    我想知道是否有人曾经使用链表进行堆排序 如果他们可以提供代码 我已经能够使用数组进行堆排序 但尝试在链表中进行排序似乎不切实际 而且在你知道的地方很痛苦 我必须为我正在做的项目实现链接列表 任何帮助将不胜感激 我也用C 答案是 你不想在链表
  • C# SmtpClient编程中如何设置带有中文的附件文件名?

    我的代码如下 ContentType ct new ContentType ct MediaType MediaTypeNames Application Octet ct Name 这是一个很长的中文文件名希望能用它在附件名中 Doc A
  • 使用 ADAL v3 使用 ClientID 对 Dynamics 365 进行身份验证

    我正在尝试对我们的在线 Dynamics CRM 进行身份验证以使用可用的 API 我能找到的唯一关于执行此操作的官方文档是 https learn microsoft com en us dynamics365 customer enga
  • 如何使用 openSSL 函数验证 PEM 证书的密钥长度

    如何验证以这种方式生成的 PEM 证书的密钥长度 openssl genrsa des3 out server key 1024 openssl req new key server key out server csr cp server
  • EntityHydrate 任务失败

    我最近安装了 Visual Studio 11 Beta 和 Visual Studio 2010 之后 我无法在 Visual Studio 2010 中构建依赖于 PostSharp 的项目 因此我卸载了 Visual Studio 1
  • 在 C++ 代码中转换字符串

    我正在学习 C 并开发一个项目来练习 但现在我想在代码中转换一个变量 字符串 就像这样 用户有一个包含 C 代码的文件 但我希望我的程序读取该文件并插入将其写入代码中 如下所示 include
  • Makefile 和 .Mak 文件 + CodeBlocks 和 VStudio

    我对整个 makefile 概念有点陌生 所以我对此有一些疑问 我正在 Linux 中使用 CodeBlocks 创建一个项目 我使用一个名为 cbp2mak 的工具从 CodeBlocks 项目创建一个 make 文件 如果有人知道更好的
  • if constexpr 中的 not-constexpr 变量 – clang 与 GCC

    struct A constexpr operator bool const return true int main auto f auto v if constexpr v A a f a clang 6 接受该代码 GCC 8 拒绝它
  • OpenGL:如何检查用户是否支持glGenBuffers()?

    我检查了文档 它说 OpenGL 版本必须至少为 1 5 才能制作glGenBuffers 工作 用户使用的是1 5版本但是函数调用会导致崩溃 这是文档中的错误 还是用户的驱动程序问题 我正在用这个glGenBuffers 对于VBO 我如
  • Linux 上的 RTLD_LOCAL 和dynamic_cast

    我们有一个由应用程序中的一些共享库构成的插件 我们需要在应用程序运行时更新它 出于性能原因 我们在卸载旧插件之前加载并开始使用新插件 并且只有当所有线程都使用旧插件完成后 我们才卸载它 由于新插件和旧插件的库具有相同的符号 我们dlopen
  • LinkLabel 无下划线 - Compact Framework

    我正在使用 Microsoft Compact Framework 开发 Windows CE 应用程序 我必须使用 LinkLabel 它必须是白色且没有下划线 因此 在设计器中 我将字体颜色修改为白色 并在字体对话框中取消选中 下划线
  • 对于 C# Express 用户来说,有哪些好的工具可以识别可能重复的代码? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 也可以看看 有什么工具可以检查重复的 VB NET 代码吗 https stackoverflow c
  • .NET 和 Mono 之间的开发差异

    我正在研究 Mono 和 NET C 将来当项目开发时我们需要在 Linux 服务器上运行代码 此时我一直在研究 ASP NET MVC 和 Mono 我运行 Ubuntu 发行版 想要开发 Web 应用程序 其他一些开发人员使用 Wind
  • Xamarin Forms Binding - 访问父属性

    我无法访问页面的 ViewModel 属性以便将其绑定到 IsVisible 属性 如果我不设置 BindingContext 我只能绑定它 有没有办法可以在设置 BindingContext 的同时访问页面的 viewmodel root
  • 在哪里可以找到 Microsoft.Build.Utilities.v3.5

    如何获取 Microsoft Build Utilities v3 5 我正在使用 StyleCop 4 7 Stylecop dll 中的 StyleCop msbuild 任务似乎依赖于 Microsoft Build Utilitie
  • 调用 .ToArray() 时出现 ArgumentException

    我有一个经常被清除的列表 代码完全是这样的 VisitorAgent toPersist List
  • 如何高效计算连续数的数字积?

    我正在尝试计算数字序列中每个数字的数字乘积 例如 21 22 23 98 99 将会 2 4 6 72 81 为了降低复杂性 我只会考虑 连续的数字 http simple wikipedia org wiki Consecutive in
  • 如何获取带有某个属性注释的所有属性?

    我刚刚从 Roslyn 开始 我想找到所有用属性名称 OneToOne 注释的属性 我启动了 SyntaxVisualizer 并能够获取对该节点的引用 但我想知道是否有更简单的方法来实现此目的 这就是我所拥有的 var prop docu
  • 如何组合两个 lambda [重复]

    这个问题在这里已经有答案了 可能的重复 在 C 中组合两个 lambda 表达式 https stackoverflow com questions 1717444 combining two lamba expressions in c
  • 如果找不到指定的图像文件,显示默认图像的最佳方式?

    我有一个普通的电子商务应用程序 我将 ITEM IMAGE NAME 存储在数据库中 有时经理会拼错图像名称 为了避免 丢失图像 IE 中的红色 X 每次显示产品列表时 我都会检查服务器中是否有与该产品相关的图像 如果该文件不存在 我会将其

随机推荐

  • 使用前瞻的 C++ std::regex 失败

    我需要从磁盘解析 txt 文件 所以我首先做了一个例子来测试正则表达式 这是我的示例代码 std string txt paragraph r nthis is the text file r ni need only this data
  • 为我的网站创建“徽章”,存储用户徽章的最佳方式?使用PHP

    我正在向我的网站添加 徽章 我想知道存储数据的最佳方式是什么 每个徽章都有一个存储在 MySQL 数据库中的 ID 每个用户在 MySQL 数据库中都有自己的行 并且每个用户都有一个 XML 格式的 userdata 文件 因此 我可以将其
  • SONAR:将此 lambda 替换为方法引用

    Sonar 告诉我 用方法引用替换这个 lambda public class MyClass private List
  • 如何使用 iText 和 Flying Saucer 在从 HTML 创建的 PDF 中嵌入字体?

    我在将波兰语字体嵌入从 HTML 转换为 PDF 时遇到问题 我的 HTML 代码正文有样式 我尝试了两种将此类 HTML 转换为 PDF 的方法 FOP 与 htmlcleaner 带飞碟的 iText 对于 FOP 我可以将所有使用的字
  • 在iOS swift中查看录音?

    是否有任何库可以记录特定的活动UIView 我遇到了这个库 ASScreenRecorder master 但当我尝试在 swift 中使用它或任何其他方式记录时 它显示出许多错误UIView哪个正在显示一些动画 例如飘落的雪花和图像的幻灯
  • Django 中的值相对于前一个值自动递增

    有没有一种方法可以相对于前一个字段自动递增字段 例如 如果前一个记录的值为 09 0001 那么下一个记录应该分配为 09 0002 等等 想法 我正在考虑重写保存方法 但我不太确定到底如何 Django 不允许您在模型中拥有多个 Auto
  • pySpark Columnsimilarities 的问题

    太长了 博士 如何使用 pySpark 比较行的相似度 我有一个 numpy 数组 我想在其中比较每一行之间的相似性 print pdArray 0 1 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 7 5 0 0 0 1 0
  • java 是否缓存方法的结果

    I useJMH指定操作的复杂度 如果您从未与 JMH 合作过 请不要担心 JMH 将刚刚推出estimateOperation方法多次 然后得到平均时间 问题 缩小 这个程序会计算Math cbrt Integer MAX VALUE 每
  • Android MediaPlayer 在某些设备上不播放声音

    我为我的应用程序发出了简单的警报声 但问题是声音在某些设备上播放 而在其他设备上则不播放 示例代码如下 public void audioPlayer leshon tingull kur ka kolision Armando 8 7 2
  • 如何隐藏或加密 JavaScript 代码? [复制]

    这个问题在这里已经有答案了 有没有办法隐藏或加密 JavaScript 代码以防止人们查看 复制和 或修改专有程序 您可以混淆它 但没有办法完全保护它 混淆器示例 https obfuscator io https obfuscator i
  • C# 枚举标志比较

    给定以下标志 Flags public enum Operations add 1 subtract 2 multiply 4 divide 8 eval 16 如何实现 IF 条件来执行每个操作 在我的尝试中 第一个条件适用于添加 评估
  • Office Web 应用程序 - 删除按钮

    有没有办法从 Office Web 应用程序中删除按钮或完整功能区 我想删除下载 添加到一个驱动器等 示例网址如下 https view officeapps live com op view aspx src www cse lehigh
  • jQuery AJAX - 意外的标记 + 解析器错误

    我今天使用 jQuery 和 AJAX 编写了一个脚本 但出现了一些错误 剧本 function changeAdmin id document ready function ta modarea id fadeOut fast ta m
  • 如何按不在数据框中的数组对数据框进行排序

    我已经在不同的上下文中多次回答过这个问题 并且我意识到在任何地方都没有指定好的规范方法 因此 设置一个简单的问题 Problem df pd DataFrame dict A range 6 B 1 2 3 print df A B 0 0
  • Python 在变量后面插入回车符和换行符,而不仅仅是换行符

    我创建了一个 python 脚本来输出 AAAA ZZZZ 等每 1 4 个字符的字母组合 它工作得很好 但是我只需要在打印变量的末尾插入换行符 因为我将其用作要在另一个脚本中使用的单词列表 我尝试同时使用 r 和 n 但是使用 n 在末尾
  • 如何通过简写“if-else”结果来中断循环?

    假设我在循环内有一个简写的 if else 语句 如下例所示 for a b c b c More unnecessary code if the result was true 我想通过条件的结果来打破循环 for a b c b bre
  • iOS 编写宏检测 3.5 英寸或 4 英寸显示器 [重复]

    这个问题在这里已经有答案了 我正在尝试编写一个宏来确定设备是 3 5 英寸还是 4 英寸 下面有一些类似的东西 define IOS OLDER THAN 6 UIDevice currentDevice systemVersion flo
  • Elixir 中的“|>”是什么意思?

    我正在阅读 github 上的一些 Elixir 代码 我发现 gt 经常被使用 它没有出现在列表中手术 http elixir lang org getting started basic operators html在文档网站上 这是什
  • 如何将 HTML 输入类型属性从“密码”更改为“文本”?

    我想更改 HTML input 元素 type 属性 从 type password 更改为 type text 我知道通过 ID 查找元素会更容易 但并非每个页面都有相同的密码输入 ID 如何定位密码输入并将其内部值更改为文本类型 我有这
  • 需要击败 GC 并在对象超出范围后将其销毁

    我有几段代码需要用互斥锁来保护 问题是代码看起来像这样 lock mylockobject if foo throw new MyException foo failed if bar throw new MyException bar f