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