使用Volatile.Read来避免锁定读取

时间:2016-10-04 14:27:53

标签: c# multithreading volatile

我正在C#中编写一个低级键盘钩子,我最重要的是避免随机的,非确定性的延迟,例如来自GC。我的第二个优先事项是让它尽可能快地运行 - 这是一个“很好的”,而不是“必须拥有”。

我的程序为键盘事件的每个“订阅者”都有一个帖子。一个订户线程可以订阅多个键盘事件。只有订阅者才能修改自己的订阅,即不允许一个帖子订阅或取消订阅另一个帖子。

我的键盘钩子的逻辑是:

  1. 确定我们正在处理的键盘事件。
  2. 查看该活动的订阅者。
  3. 将事件放入每个订阅者的队列中。
  4. 我目前对第2步的想法是从ConcurrentDictionary获取订阅者信息。这是HotkeySubscriberInfo的简化版本:

    class HotkeySubscriberInfo
    {
        private ISet<Subscriber> _subscribers;
        private Subscriber[] _memoizedSubscriberEnumeration;
        private object _writeMutex;
        private object _readMutex;
    }
    

    HotkeySubscriberInfo会像这样突变:

    lock (_writeMutex)
    {
        // add or remove a subscriber
        Subscriber[] memoized = subscribers.ToArray();
        lock (_readMutex)
        {
            _memoizedSubscriberEnumeration = memoized;
        }
    }
    

    键盘钩子只会锁定_readMutex,将数组放入局部变量并对其进行for循环。

    我的问题是:我可以摆脱_readMutex并在键盘钩子中使用Volatile.Read吗?我知道这意味着键盘钩并不总是“立即”获得“新鲜”值,但只要该值不太陈旧(例如订阅者未订阅,在按下某人之前一整秒通过),这是可接受的行为热键和订阅者无论如何都会获取热键,因为订阅者列表是陈旧的。)

0 个答案:

没有答案