Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 可以(应该?)懒惰<;T>;是否用作缓存技术?_C#_Multithreading_Caching_Locking_Lazy Loading - Fatal编程技术网

C# 可以(应该?)懒惰<;T>;是否用作缓存技术?

C# 可以(应该?)懒惰<;T>;是否用作缓存技术?,c#,multithreading,caching,locking,lazy-loading,C#,Multithreading,Caching,Locking,Lazy Loading,我想使用.NET的Lazy类来实现线程安全缓存。假设我们有以下设置: class Foo { Lazy<string> cachedAttribute; Foo() { invalidateCache(); } string initCache() { string returnVal = ""; //CALCULATE RETURNVAL HERE return re

我想使用
.NET
Lazy
类来实现线程安全缓存。假设我们有以下设置:

class Foo
{
    Lazy<string> cachedAttribute;

    Foo()
    {
        invalidateCache();
    }

    string initCache()
    {
        string returnVal = "";
        //CALCULATE RETURNVAL HERE
        return returnVal;
    }

    public String CachedAttr
    {
        get
        {
            return cachedAttribute.Value;
        }
    }

    void invalidateCache()
    {
        cachedAttribute = new Lazy<string>(initCache, true);
    }
}
class-Foo
{
懒惰的缓存属性;
Foo()
{
失效缓存();
}
字符串initCache()
{
字符串returnVal=“”;
//在这里计算RETURNVAL
返回值;
}
公共字符串CachedAttr
{
得到
{
返回cachedAttribute.Value;
}
}
void invalidateCache()
{
cachedAttribute=newlazy(initCache,true);
}
}
我的问题是:

  • 这样行吗
  • 锁必须如何工作
  • 我觉得我好像丢失了一把锁,就在我的生命中,我不知道它是什么

    我肯定这在什么地方有问题,我只是不知道在哪里

    [编辑]

    好吧,看来我是对的,有些事情我没想过。如果一个线程看到一个过时的缓存,那将是一件非常糟糕的事情,所以看起来“懒惰”是不够安全的。不过,该属性经常被访问,因此我正在进行预成熟优化,希望我能学到一些东西,并有一个将来用于线程安全缓存的模式。我会继续努力的


    注意:我决定使对象线程不安全,并对对象的访问进行仔细控制。

    好吧,这不是线程安全的,因为一个线程在另一个线程失效后看到新值后仍然可以看到旧值-因为第一个线程可能没有看到对
    cachedAttribute
    的更改。从理论上讲,这种情况可能永远持续下去,尽管可能性很小:)


    使用
    Lazy
    作为不变值的缓存对我来说似乎是一个更好的主意-更符合它的意图-但是如果您能够处理在另一个线程中使用旧的“无效”值任意长时间的可能性,我想这没问题。

    cachedAttribute是一个共享资源,需要防止并发修改

    锁保护它

    private readonly object gate = new object();
    
    public string CachedAttr
    {
        get
        {
            Lazy<string> lazy;
            lock (gate)                         // 1. Lock
            {
                lazy = this.cachedAttribute;    // 2. Get current Lazy<string>
            }                                   // 3. Unlock
            return lazy.Value                   // 4. Get value of Lazy<string>
                                                //    outside lock
        }
    }
    
    void InvalidateCache()
    {
        lock (gate)                             // 1. Lock
        {                                       // 2. Assign new Lazy<string>
            cachedAttribute = new Lazy<string>(initCache, true);
        }                                       // 3. Unlock
    }
    
    private readonly object gate=new object();
    公共字符串CachedAttr
    {
    得到
    {
    懒惰;
    锁(门)//1.锁
    {
    lazy=this.cachedAttribute;//2.获取当前lazy
    }//3.解锁
    返回lazy.Value//4.获取lazy的值
    //外锁
    }
    }
    void InvalidateCache()
    {
    锁(门)//1.锁
    {//2.分配新任务
    cachedAttribute=newlazy(initCache,true);
    }//3.解锁
    }
    
    或使用:

    void InvalidateCache()
    {
    Exchange(ref cachedAttribute,new Lazy(initCache,true));
    }
    

    volatile
    在这种情况下也可以工作,但它会让我头疼。

    是的,无效值在这种情况下并不好(至少不是任意长的值)。谢谢。我建议将
    cachedAttribute
    的检索放在锁中,但让
    Value
    的计算在锁外进行。谢谢您的快速回答。多线程让我头疼,所以别担心,如果你的担心是不稳定的,那你就有好朋友了!这两种情况中的任何一种都会阻止读取旧值吗?@Cpfohl:不会,我的答案只是阻止同时修改
    cachedAttribute
    。@Jon Skeet提出的问题依然存在。
    void InvalidateCache()
    {
        Interlocked.Exchange(ref cachedAttribute, new Lazy<string>(initCache, true));
    }