C# 内存事件源算法-是否正确?它是线程安全的吗?

C# 内存事件源算法-是否正确?它是线程安全的吗?,c#,thread-safety,event-sourcing,C#,Thread Safety,Event Sourcing,抱歉,这个问题有点推测性 我正在使用内存中的静态对象编写一个Cms来保存系统的当前状态,并且正在使用事件源创建一个事件日志,我可以用它来重建对象状态,并提供回滚等功能(看看你是否不知道我在讲什么) 如果执行或重建需要很长时间,那么可能会有大量写操作堆积起来,并且可能会使用大量内存,除此之外,这其中是否存在任何错误,特别是与并发相关的错误?如果有人使用Read的公共getter或setter,您可能会遇到问题,因为这里没有同步。如果有人在另一个线程在Update中修改该属性的同时使用该属性,则读取

抱歉,这个问题有点推测性

我正在使用内存中的静态对象编写一个Cms来保存系统的当前状态,并且正在使用事件源创建一个事件日志,我可以用它来重建对象状态,并提供回滚等功能(看看你是否不知道我在讲什么)


如果执行或重建需要很长时间,那么可能会有大量写操作堆积起来,并且可能会使用大量内存,除此之外,这其中是否存在任何错误,特别是与并发相关的错误?

如果有人使用
Read
的公共getter或setter,您可能会遇到问题,因为这里没有同步。如果有人在另一个线程在
Update
中修改该属性的同时使用该属性,则读取的内容可能会获取一个过时的值,或者通过写入所做的更改可能会自动丢失


那房子真的需要公开吗?并且可以公开写入?

您确定没有线程处于饥饿模式吗?因为锁{}块不应该占用太多时间。另外,如果一个线程获得了alock,并且它的catch块抛出了一个异常,那么您可以在catch{}块中抛出它。那么你认为锁会被释放吗?嗯,也许这会作为一个并发列表或其他东西更好,让操作在那里排队。。。说得好!我认为例外情况是安全的:因为他是从捕捉中抛出的,我想锁永远不会被释放。如果我错了,请纠正我:)另外,如果线程抛出异常,应用程序将崩溃。defs不可写-尽管我想知道它是否应该是易变的。它需要是公共的,这样应用程序的其余部分就可以得到它的手,对吗?可能它应该是一个具有公共getter的易失性私有字段…@mcintye321:如果您希望能够在不同步的情况下从不同线程对其进行读/写,那么应该将其标记为易失性。查看文档了解
volatile
:但即使使用
volatile
,您仍可能存在一些不必要的竞态条件。
public class Cms
{
    private static object WriteLock = new object();
    public static Cms Read { get; set; }
    static Cms Write { get; set; }

    static Cms()
    {
        Read = RebuildFromActionLog();
        Write = RebuildFromActionLog();
    }

    public static void Update(Action action)
    {

        lock (WriteLock)
        {                
            try
            {
                action.Apply(Write);
            }
            catch(Exception ex)
            {
                Write = RebuildFromActionLog(); //ditch the potentially messed up Write model
                throw;
            }
            LogAction(action); //the action was a keeper, so keep it
            Read = Write; //ditch the current read only model - it will continue to be used by any requests that have grabbed it
            Write = RebuildFromActionLog(); //get a new model ready for the next write
        }
    }
...
}