C# 这是已知的线程安全同步/锁定模式吗?

C# 这是已知的线程安全同步/锁定模式吗?,c#,design-patterns,c#-4.0,thread-safety,C#,Design Patterns,C# 4.0,Thread Safety,我觉得我是在重新发明轮子,很有可能有人已经用头撞了代码,想出了一个好的、稳定的、经过测试的模式来解决这个问题,而我还没有遇到它 我想出了下面的解决方案,现在似乎对我很有效。 它应该提供一个一致的接口来处理应该以线程安全方式访问的对象 将其称为“原子”对象get/set holder,这是其他地方使用的模式吗 以下是界面: public interface ISynched<T> { bool Read( ref T value ); bool Read( ref T

我觉得我是在重新发明轮子,很有可能有人已经用头撞了代码,想出了一个好的、稳定的、经过测试的模式来解决这个问题,而我还没有遇到它

我想出了下面的解决方案,现在似乎对我很有效。
它应该提供一个一致的接口来处理应该以线程安全方式访问的对象

将其称为“原子”对象get/set holder,这是其他地方使用的模式吗

以下是界面:

public interface ISynched<T>
{
    bool Read( ref T value );
    bool Read( ref T value, TimeSpan timeout );

    bool Write( T value );
    bool Write( T value, TimeSpan timeout );

    bool Do( Action<T> roAction );
    bool Do( Action<T> roAction, TimeSpan timeout );
    bool Do( Action<T, Action<T>> rwAction );
    bool Do( Action<T, Action<T>> rwAction, TimeSpan timeout );
}
公共接口已同步
{
布尔读数(参考T值);
bool读取(参考T值,时间间隔超时);
bool写入(T值);
bool写入(T值,TimeSpan超时);
bool-Do(动作-动作);
bool Do(动作动作、时间间隔超时);
bool Do(动作rwAction);
bool Do(动作rwAction,TimeSpan超时);
}
实施情况如下:

public class Synched<T>: ISynched<T>
{
    static public readonly TimeSpan Infinity = TimeSpan.FromMilliseconds(-1);

    private T _value;

    public static Synched<T> MakeSynched( T value )
    {
        return new Synched<T>() { _value = value };
    }

    private Synched() {}

    public bool Read( ref T value )
    {
        return Read( ref value, Infinity );
    }
    public bool Read( ref T value, TimeSpan timeout )
    {
        var tmp = default(T);
        var success = Do( (v) => tmp = v, timeout );
        if( success ) value = tmp;
        return success;
    }

    public bool Write( T value )
    {
        return Do( (v, set) => set(v) );
    }
    public bool Write( T value, TimeSpan timeout )
    {
        return Do( (v, set) => set(v), timeout );
    }

    public bool Do( Action<T> roAction )
    {
        return Do( roAction, Infinity );
    }
    public bool Do( Action<T> roAction, TimeSpan timeout )
    {
        bool lockWasTaken = false;
        try
        {
            Monitor.TryEnter(this, timeout, ref lockWasTaken);
            if(!lockWasTaken) return false;

            roAction( _value );
            return true;
        }
        finally
        {
            if (lockWasTaken) Monitor.Exit(this);
        }
    }

    public bool Do( Action<T, Action<T>> rwAction )
    {
        return Do( rwAction, Infinity);
    }
    public bool Do( Action<T, Action<T>> rwAction, TimeSpan timeout )
    {
        bool lockWasTaken = false;
        try
        {
            Monitor.TryEnter(this, timeout, ref lockWasTaken);
            if(!lockWasTaken) return false;

            rwAction( _value, value => _value = value );
            return true;
        }
        finally
        {
            if (lockWasTaken) Monitor.Exit(this);
        }
    }
}
已同步公共类:已同步
{
静态公共只读TimeSpan Infinity=TimeSpan.FromMillistics(-1);
私人T_值;
公共静态同步MakeSynched(T值)
{
返回新的Synched(){u value=value};
}
私有同步(){}
公共布尔读取(参考T值)
{
返回读取(参考值,无穷大);
}
公共布尔读取(参考T值,TimeSpan超时)
{
var tmp=默认值(T);
var success=Do((v)=>tmp=v,超时);
如果(成功)值=tmp;
回归成功;
}
公共布尔写入(T值)
{
返回Do((v,set)=>set(v));
}
公共bool写入(T值,TimeSpan超时)
{
返回Do((v,set)=>set(v),超时);
}
公共图书馆(行动和行动)
{
返回Do(roAction,无穷大);
}
公共bool Do(操作roAction,TimeSpan超时)
{
bool lockwastake=false;
尝试
{
Monitor.TryEnter(这个、超时、ref lockwasted);
如果(!lockwastake)返回false;
roAction(_值);
返回true;
}
最后
{
如果(锁定)监视器。退出(此);
}
}
公共部门(行动和行动)
{
返回Do(rAction,无穷大);
}
公共bool Do(操作rwAction,TimeSpan超时)
{
bool lockwastake=false;
尝试
{
Monitor.TryEnter(这个、超时、ref lockwasted);
如果(!lockwastake)返回false;
rwAction(_值,value=>_值=value);
返回true;
}
最后
{
如果(锁定)监视器。退出(此);
}
}
}
以及一个附加的静态非泛型类,使同步对象创建更容易编码:

public static class Synched
{
    public static Synched<T> MakeSynched<T>( T value )
    {
        return Synched<T>.MakeSynched( value );
    }
}
已同步公共静态类
{
公共静态同步MakeSynched(T值)
{
返回Synched.MakeSynched(值);
}
}
编辑:我已经改变了这个例子,使之更有意义 示例用例如下所示(代码没有任何意义,只是一个示例(一个糟糕的示例):

var synchedCol=Synched.MakeSynched(新列表());
synchedCol.Do(c=>{
c、 添加(newsomeclass());
c、 添加(newsomeclass(){Property1=“something”});
} );
var i=1;
某类val;
synchedCol.Do(c=>val=c[i]);
var i=1;
synchedCol.Do(c=>{
if(c[i].Property1==“某物”)
{
c、 删除(c[i]);
}
});
那么我走对了吗?有没有人遇到过类似的事情?有没有类似的现有模式?

不要试图重新发明轮子

如果想要线程安全的集合,请从命名空间中选择一个


例如,
blockingcollection
为实现
IProducerConsumerCollection
的线程安全集合提供了阻塞和边界功能。这将比您的实现性能更好,因为它实现了生产者/消费者(读写器)模式。这意味着读卡器不必同步,也不会相互阻塞。

根据您正在做的事情,我建议一个好的模式应该是有一个接受
函数的方法,该函数应该——给定数据项的现有值,生成一个新值;调用者必须为可能的情况做好准备如果基础数据项在执行时被写入,则委托可能被多次调用。例如,两个调用方尝试使用计算
(x)=>x+1
Func
更新同一数据项(最初为5),两个委托都可能被调用,值为5(计算6),一个更新将成功,另一个将使用值6(计算7)重新调用其委托,然后存储该结果

当争用不严重时,如果调用方准备多次调用该函数,则该方法相对容易正确工作。但是,如果该函数需要很长时间进行计算,并且资源争用较多,则直接的方法可能会有点慢。它的性能可能会有所提高然而,让代码检测争用并开始使用监视器对象来实现“定时建议锁”是不合理的:如果一个客户端的委托正在计算某个项的新值,则允许另一个客户端访问该项将导致挂起客户端或新客户端所做的工作被浪费。根据挂起客户端的函数运行的时间,它的努力可能永远不会有任何结果,因此另一方面,如果新客户机等待资源的总时间相对于客户机的娱乐时间足够长,那么我们可以有逻辑地认为
var synchedCol = Synched.MakeSynched( new List<SomeClass>() );

synchedCol.Do( c => {
    c.Add(new SomeClass());
    c.Add(new SomeClass() { Property1 = "something" } );
} );

var i = 1;
SomeClass val;
synchedCol.Do( c => val = c[i] );

var i = 1;
synchedCol.Do( c => {
    if( c[i].Property1 == "something" )
    {
        c.Remove(c[i]);
    }
});