【问题标题】:C#: How do I read/write IntPtr to/from memory atomically?C#:如何以原子方式从内存读取/写入 IntPtr?
【发布时间】:2019-01-23 10:20:39
【问题描述】:

我正在像这样在内存中读/写一个全局变量:

var old = Marshal.ReadIntPtr(ptr, ofs);
Marshal.WriteIntPtr(ptr, ofs, nwv);

其中 ptr 是内存中的基指针,ofs 是变量偏移量,旧变量接收当前值,nwv 是全局变量的新值。它运作良好,但我想知道是否有办法以原子方式进行?我知道有 Interlocked.Exchange 方法,它允许切换 IntPtrs,但我不知道如何正确地将 ptr+ofs 转换为 ref IntPtr。 Interlocked.Exchange 会自动进行 IntPtrs 切换吗?

【问题讨论】:

  • @Johnny,是的,我可以,但是如何将 ptr(指向内存的实际指针)转换为 Interlocked.Echange 所需的 ref IntPtr?
  • @Johnny 你不懂。 ptr 是指向某个内存位置的指针,当我执行 ref ptr 时,我得到了 ptr 变量在堆栈上的地址,我需要 ref 指向内存位置。
  • @Johnny - IntPtrs 上的 Interlocked.Exchange 替换了 IntPtr 变量 的内容。它不会影响该变量当前指向 的内存(除非它指向自身),这就是您的ptr 标识为目标 位置的内存。你在思考这个问题时缺少了一定程度的间接性。
  • 如果它“运行良好”,那么以原子方式执行它的意义何在?它可能非常昂贵,具体取决于预取器和存储缓冲区的状态,它可能会慢约 150 倍。

标签: c# .net


【解决方案1】:

您需要一个锁来避免另一个 C# 方法在您的“原子”操作中间访问该位置。简化:

static object locker = new object();
lock (locker) {
  //read
  //write
}

一次只有一个线程可以锁定locker。其他争夺锁的线程被阻塞,直到锁被释放。

【讨论】:

  • 这个全局变量被我无法控制的非托管代码访问。
猜你喜欢
  • 1970-01-01
  • 2015-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多