与读取并发,但与变异并发 [英] Concurrency with reading but locking with mutating

查看:63
本文介绍了与读取并发,但与变异并发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种解决方案,该解决方案允许多个线程读取共享资源(允许并发),但是一旦线程进入变异块,然后锁定这些读取线程,以实现两全其美.

I'm looking for a solution that allows multiple threads to read the shared resource (concurrency permitted) but then locks these reading threads once a thread enters a mutating block, to achieve best of both world.

我已经查看了这个参考,但似乎解决方案是锁定读写线程.

I've looked up this reference but it seems the solution is to lock both reading and writing threads.

class Foo {

    List<string> sharedResource;

    public void reading() // multiple reading threads allowed, concurrency ok, lock this only if a thread enters the mutating block below.
    {

    }

    public void mutating() // this should lock any threads entering this block as well as lock the reading threads above
    {
        lock(this)
        {
        }
    }
}

在C#中有这样的解决方案吗?

Is there such a solution in C#?

修改

GetMultiton和构造函数中同时输入的所有线程都应返回相同的实例.希望它们是线程安全的.

All threads entering in both GetMultiton and constructor should return the same instance. want them to be thread safe.

class Foo: IFoo {
    public static IFoo GetMultiton(string key, Func<IFoo> fooRef)
    {
        if (instances.TryGetValue(key, out IFoo obj))
        {
            return obj;
        }
        return fooRef();
    }

     public Foo(string key) {
          instances.Add(key, this);
     }
}

     protected static readonly IDictionary<string, IFoo> instances = new ConcurrentDictionary<string, IFoo>();

使用

  Foo.GetMultiton("key1", () => new Foo("key1"));

推荐答案

此行为多个线程可以同时进入读取锁,但是如果尝试使用写入锁,它将阻塞直到所有当前读取器完成,然后阻塞所有新的写入器和新读取器,直到写入锁结束.

Multiple threads can enter the read lock at the same time but if a write lock tries to be taken it will block till all current readers finish then block all new writers and new readers till the write lock finishes.

更新后,您根本不需要锁.只需使用ConcurrentDictionary中的GetOrAdd

With your update you don't need locks at all. Just use GetOrAdd from ConcurrentDictionary

class Foo: IFoo {
    public static IFoo GetMultiton(string key, Func<IFoo> fooRef)
    {
        return instances.GetOrAdd(key, k=> fooRef());
    }

     public Foo(string key) {
          instances.Add(key, this);
     }
}

请注意,可能多次调用fooRef(),但是只有第一个返回的线程将用作所有线程的结果.如果只想一次调用fooRef(),则将需要稍微复杂一些的代码.

Note that fooRef() may be called more than once, but only the first one to return will be used as the result for all the threads. If you want fooRef() to only be called once it will require slightly more complicated code.

class Foo: IFoo {
    public static IFoo GetMultiton(string key, Func<IFoo> fooRef)
    {
        return instances.GetOrAdd(key, k=> new Lazy<IFoo>(fooRef)).Value;
    }

     public Foo(string key) {
          instances.Add(key, new Lazy<IFoo>(()=>this);
     }
}

     protected static readonly IDictionary<string, Lazy<IFoo>> instances = new ConcurrentDictionary<string, Lazy<IFoo>>();

这篇关于与读取并发,但与变异并发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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