易变结构和结构集合 [英] Volatile for structs and collections of structs

查看:60
本文介绍了易变结构和结构集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想利用网络智慧来澄清有关.net中多线程的一些情况.互联网上有很多关于它的东西,但是我找不到我的问题的好答案.

I would like to use net wisdom to clarify some moments regarding multi-threading in .net. There are a lot of stuff in the internet about it however I was not able to find a good answer to my question.

比方说,我们希望通过并发线程的安全性来维护类中某些内容的状态.最简单的情况是当状态为int时:

Let say we want to maintain a state of something in our class with safety for concurrent threads. Easy case is when state is int:

class Class1
{
    volatile int state = 0;

    public int State
    {
        get
        {
            return state;
        }
    }

    public Action<int> StateUpdated;

    public void UpdateState(int newState)
    {
        state = newState;

        if (StateUpdated != null)
            StateUpdated(newState);
    }
}

在这种情况下,

'volatile'应该足够了.无论线程需要获取当前状态,它都可以使用状态"属性,该属性永远不会被缓存.无论哪个线程想要更​​新状态,都可以使用"UpdateState"安全地进行.

'volatile' should be enough in this case. Whatever thread needs to get current state it can use 'State' property which will never be cached. Whatever thread wants to update state it can do it safely using 'UpdateState'.

但是,如果状态是结构,该怎么办?完整的锁定"是唯一的方法吗?附带的问题:变量是否仍可以缓存在锁中?

However, what to do if state is a structure? Is a complete 'lock' the only way? Side question: can a variable still be cached inside the lock?

struct StateData
{
    //some fields
}

class Class1
{
    StateData state;

    public StateData State
    {
        get
        {
            return state;
        }
    }

    public Action<StateData> StateUpdated;

    public void UpdateState(StateData newState)
    {
        state = newState;

        if (StateUpdated != null)
            StateUpdated(newState);
    }
}

最后是主要问题:此代码足以在多线程环境中管理状态对象的集合吗?否则可能存在一些隐藏的问题.

And eventually the main question: will this code be sufficient for managing a collection of state objects in multi-threading environment? Or there might be some hidden problems.

public struct StateData
{
    //some fields
}

public delegate void StateChangedHandler(StateData oldState, StateData newState);

class Class1
{
    ConcurrentDictionary<string, StateData> stateCollection = new ConcurrentDictionary<string, StateData>();

    public StateData? GetState(string key)
    {
        StateData o;

        if (stateCollection.TryGetValue(key, out o))
            return o;
        else
            return null;
    }

    public StateChangedHandler StateUpdated;

    void UpdateState(string key, StateData o)
    {
        StateData? prev = null;

        stateCollection.AddOrUpdate(key, o,
            (id, old) =>
            {
                prev = old;

                return o;
            }
            );

        if (prev != null && StateUpdated != null)
            StateUpdated(prev.Value, o);
    }
}

感谢您的回答.

推荐答案

但是,如果状态是结构,该怎么办?完整的锁定"是唯一的方法吗?

However, what to do if state is a structure? Is a complete 'lock' the only way?

volatile 关键字仅适用于可以原子更新的类型,例如引用类型变量,指针和原始类型.

The volatile keyword is applicable only to types that can be updated atomically, such as reference type variables, pointers, and primitive types.

但是,请注意,除了仅访问标记的变量之外, volatile 还提供了一些保证.特别是,在从 标记相同的读取之后,从内存读取的任何代码都会看到在写入 volatile 标记的内存位置之前发生的所有对内存的写入.>标记为易失性的内存位置.

However, note that volatile provides some guarantees besides just access to the marked variable. In particular, all writes to memory that occur before a write to a volatile-marked memory location will be seen by any code that reads from memory after reading from that same volatile-marked memory location.

从理论上讲,这意味着您可以使用 volatile 字段为其他内存位置提供类似volatile的行为.

In theory, this means you can use a volatile field to provide volatile-like behavior for other memory locations.

尽管在实践中仍然存在一个问题:对相同内存位置的新写入可能可见或不可见,当然,并非所有写入都可以原子完成.因此,使用 volatile 确实仅对可以标记为易失性的其他内存位置有效,即使这样也不能确保您不会获得 newer 值会超出 volatile 标记的内存位置,否则将指示该值.

In practice though, there is still a problem: new writes to the same memory locations may or may not be visible, and of course not all writes can be completed atomically. So this use of volatile is really only good for other memory locations that could be marked volatile, and even then doesn't ensure you won't get newer values than the volatile-marked memory location would otherwise indicate.

很长一段话,您应该只使用 lock 并完成它.:)

Which is a long way of saying, you should just use lock and be done with it. :)

旁边的问题:变量是否仍可以缓存在锁中?

Side question: can a variable still be cached inside the lock?

我不确定您对这个问题的意思.但总的来说:只要不影响单个线程中观察到的代码行为,编译器就可以进行优化.如果您考虑的缓存类型不会违反此规则,则可以允许它.否则就不会.

I'm not entirely sure what you mean by this question. But in general: the compilers are permitted to make optimizations as long as those optimizations don't affect the observed behavior of the code in a single thread. If the type of caching you are thinking of would not violate this rule, it might be allowed. Otherwise it wouldn't be.

此代码足以在多线程环境中管理状态对象的集合吗?

will this code be sufficient for managing a collection of state objects in multi-threading environment?

发布的代码似乎还不错,至少可以确保字典始终提供一致的状态值.

The code as posted seems fine, at least as far as ensuring that the dictionary is always providing coherent state values.

这篇关于易变结构和结构集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆