标签: readerwriterlockslim

混合锁和联锁操作是否安全?

我有一些必须是线程安全的代码,其行为类似于:


protected long m_RunningValue
protected long m_RunningCounter
protected object m_Lock = new object();

public long RunningValue { get { return Interlocked.Read(m_RunningValue); } }
public long RunningCounter { get { return Interlocked.Read(m_RunningCounter); } }

public void DoCalculation(int newValue, int newQuantity)
{
   lock(m_Lock)
   {
       Interlocked.Add(ref m_RunningValueA, newValue);
       Interlocked.Add(ref m_RunningCounter, newQuantity);
       if(Interlocked.Read(ref newQuantity) == 0)
       { 
         ...m_RunningValue gets further modified here
       }
   }
}

计算必须锁定值和计数器,否则竞争条件可能影响if(...)块,但是在读出时它们根本不需要同步,即如果计数器和值在尝试之间发生变化读两个,这对我来说是100%的好.

读取时的互锁用于读取64位值的线程安全性.

  1. 混合联锁和锁这样安全吗?我在其他网页上看到混合它们是不安全的,但是如果这意味着混合它们是引入细微错误的好方法,或者如果在系统级别这会破坏所涉及的数据结构,我无法找到澄清.

  2. 所有这些互锁(64位.NET 4.0运行时)的成本是否完全违背了在属性get()方法周围保存ReaderWriterSlim锁的目的?

c# interlocked thread-safety readerwriterlockslim

6
推荐指数
1
解决办法
1418
查看次数

Windows条件变量与事件

我们可以使用新的条件变量原语或windows事件来同步WinNT v6.x或更高版本中的线程.考虑以下两种方法,我们希望工作者在main中设置"go"的同时运行,否则它们都应该阻塞.

/*language C code*/
/*Windows Condition Variable*/
int go=0;
CONDITION_VARIABLE cv;
SRWLOCK lock;
void workers()
{
    AcquireSRWLockShared(&lock);
    if(go==0)
    {
        SleepConditionVariableSRW(&cv, &lock, INFINITE, CONDITION_VARIABLE_LOCKMODE_SHARED);
    }
    ReleaseSRWLockShared(&lock);
    /*
    Workers continue...
    */
}
void main()
{
    int i;
    InitializeConditionVariable(&cv);
    InitializeSRWLock(&lock);
    for(i=0;i<10;i++)
    {
        CreateThread(0, 0, workers, 0, 0, 0);
    }
    AcquireSRWLockExclusive(&lock);
    go=1;
    ReleaseSRWLockExclusive(&lock);
    WakeAllConditionVariable(&cv);
}
Run Code Online (Sandbox Code Playgroud)

要么

/*language C code*/
/*Windows Event*/
HANDLE go;
void workers()
{
    WaitForSingleObject(go, INFINITE);
    /*
    Workers continue...
    */
}
void main()
{
    int i;
    go=CreateEvent(0,1,0,0); /*No security descriptor, Manual …
Run Code Online (Sandbox Code Playgroud)

c windows multithreading condition-variable readerwriterlockslim

6
推荐指数
1
解决办法
5828
查看次数

ReaderWriterLockSlim.EnterUpgradeableReadLock()始终是死锁?

我非常熟悉,ReaderWriterLockSlim但我EnterUpgradeableReadLock()最近在一个类中尝试实现...不久之后我意识到当2个或更多线程运行代码时,这几乎肯定是一个保证死锁:

Thread A --> enter upgradeable read lock
Thread B --> enter upgradeable read lock
Thread A --> tries to enter write lock, blocks for B to leave read
Thread B --> tries to enter write lock, blocks for A to leave read
Thread A --> waiting for B to exit read lock
Thread B --> waiting for A to exit read lock
Run Code Online (Sandbox Code Playgroud)

我在这里错过了什么?

编辑

添加了我的场景的代码示例.该Run()方法将由两个或多个线程同时调用.

public class Deadlocker
{
    private readonly ReaderWriterLockSlim _lock …
Run Code Online (Sandbox Code Playgroud)

c# multithreading thread-safety readerwriterlockslim

6
推荐指数
1
解决办法
5798
查看次数

再次双重检查锁定和C#

最近我一直在重构我的一些C#代码,我发现了一些双重检查锁定实践.那时我不知道这是一个不好的做法,我真的想摆脱它.

问题是我有一个应该被懒惰地初始化并且经常被许多线程访问的类.我也不想将初始化移动到静态初始化器,因为我计划使用弱引用来保持初始化对象在内存中保持太长时间.但是,如果需要,我想"恢复"对象,确保以线程安全的方式发生这种情况.

我想知道是否在C#中使用ReaderWriterLockSlim并在第一次检查之前输入UpgradeableReadLock,然后如果需要,为初始化输入写锁定将是可接受的解决方案.以下是我的想法:

public class LazyInitialized
{
    private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();

    private volatile WeakReference _valueReference = new WeakReference(null);
    public MyType Value
    {
        get
        {
            MyType value = _valueReference.Target as MyType;
            _lock.EnterUpgradeableReadLock();
            try
            {
                if (!_valueReference.IsAlive) // needs initializing
                {
                    _lock.EnterWriteLock();
                    try
                    {
                        if (!_valueReference.IsAlive) // check again
                        {
                            // prevent reading the old weak reference
                            Thread.MemoryBarrier(); 
                            _valueReference = new WeakReference(value = InitializeMyType());
                        }
                    }
                    finally
                    {
                        _lock.ExitWriteLock();
                    }
                }
            }
            finally
            {
                _lock.ExitUpgradeableReadLock();
            }
            return value;
        } …
Run Code Online (Sandbox Code Playgroud)

c# locking readerwriterlockslim double-checked-locking

5
推荐指数
1
解决办法
2094
查看次数

与ReaderWriterLockSlim并行的Parallel.ForEach死锁

我的应用程序中有一个有趣的死锁问题.有一个内存数据存储,它使用ReaderWriterLockSlim来同步读写.其中一种读取方法使用Parallel.ForEach在给定一组过滤器的情况下搜索商店.其中一个过滤器可能需要对同一商店进行恒定时间读取.这是产生死锁的场景:

更新:下面的示例代码.实际方法调用更新步骤
鉴于单一实例storeConcreteStoreThatExtendsGenericStore

  1. Thread1获取商店的读锁定 - store.Search(someCriteria)
  2. Thread2尝试使用写锁定来更新存储 - store.Update()- 阻塞Thread1
  3. Thread1对商店执行Parallel.ForEach以运行一组过滤器
  4. Thread3(由派生线程1的Parallel.ForEach)尝试恒定时读取的商店.它尝试获取读锁定但在Thread2的写锁定后被阻止.
  5. Thread1无法完成,因为它无法加入Thread3. 线程2无法完成,因为它阻止后面线程1.

理想情况下,如果当前线程的祖先线程已经具有相同的锁,我想要做的就是尝试获取读锁.有没有办法做到这一点?或者还有另一种/更好的方法吗?

public abstract class GenericStore<TKey, TValue>
{
    private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
    private List<IFilter> _filters;  //contains instance of ExampleOffendingFilter

    protected Dictionary<TKey, TValue> Store { get; private set; }

    public void Update()
    {
        _lock.EnterWriterLock();
        //update the store
        _lock.ExitWriteLock();
    }

    public TValue GetByKey(TKey …
Run Code Online (Sandbox Code Playgroud)

c# deadlock readerwriterlockslim parallel.foreach

5
推荐指数
1
解决办法
1457
查看次数

ReaderWriterLockSlim 是否能够抵抗 ThreadAbortException?

我想检查以下代码是否能够抵抗 ThreadAbortException 并且不会导致孤儿锁。如果不是,那么避免孤儿锁的最佳模式是什么?

ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();

public void DoStaff()
{
  _lock.EnterWriteLock();
  //Is this place where ThreadAbotException can corrupt my code, or is there JIT optimalization which prevent this from happening??? 
  try
  {
    ...
  }
  finally
  {
    _lock.ExitWriteLock();
  }
}
Run Code Online (Sandbox Code Playgroud)

根据以下链接http://chabster.blogspot.cz/2013/07/a-story-of-orphaned-readerwriterlockslim.html,有(或至少有)可能的方法如何创建孤儿锁,但我正在运行示例编码了一段时间,没有任何运气。

我正在使用.NET 4.0

调试和发布中的行为有什么区别吗?

.net c# readerwriterlockslim threadabortexception

5
推荐指数
1
解决办法
930
查看次数

c#中的可升级读卡器锁

我有一个在多个线程之间共享的字典.每个线程根据给定的键从字典中读取特定值,但是 - 如果字典中不存在该键,则线程需要将其添加到字典中.
为了解决同步问题,我虽然使用了ReaderWriterLockSlim类,它基本上给了我读者 - 作者锁定同步(意思是读者可以并行运行,但一次只能运行一个作者......)但为读者添加了升级选项.使用升级选项,我可以测试给定的密钥是否已经在字典中,如果没有 - 升级锁并写入它,承诺每个密钥只添加一个.

我的问题是,我不能一次创建两个可升级的锁 - 这意味着这个解决方案是不好的...... :(

有人可以向我解释为什么微软选择以这种方式实施可升级锁(我一次不能拥有多个可升级的锁......),并且让我知道如何通过自己实现可升级的锁\给我的另一个想法是同步我的共享字典?

c# multithreading synchronization readerwriterlockslim

3
推荐指数
1
解决办法
1106
查看次数

ReaderWriteLockSlim或Lock

我使用ConcurrentBag在运行时存储对象.在某些时候,我需要清空行李并将行李内容存储到列表中.这就是我做的:

        IList<T> list = new List<T>();

        lock (bag)
        {
            T pixel;

            while (bag.TryTake(out pixel))
            {
                list.Add(pixel);
            }
        }
Run Code Online (Sandbox Code Playgroud)

我的问题是同步,据我在书中读到的锁比其他同步方法更快.来源 - http://www.albahari.com/threading/part2.aspx.

性能是我的第二个问题,我想知道我是否可以在此时使用ReaderWriterLockSlim.使用ReaderWriterLockSlim会有什么好处?原因是,我不希望此操作阻止传入的请求.

如果是,我应该使用可升级锁吗?

有任何想法吗 ?评论?

c# multithreading synchronization locking readerwriterlockslim

3
推荐指数
1
解决办法
443
查看次数

ReaderWriterLockSlim与Double Lock Check模式

编辑:从我已经得到的答案中,我了解我提出的第一个解决方案,并不是真正的“不阻止读取”,因为只有一个线程可以输入可升级的锁,而在读取被释放之前不能采用写入锁...

所以我的问题是,如果不存在,如何以正确的方式使第一个解决方案成为“非阻塞读取”?


我试图了解两种非阻塞多线程读取的解决方案。以下两个解决方案之间有什么区别(也许我仍然不了解某些事情,但是我正在尝试):

/// <summary>
/// ReaderWriterLockSlim pattern
/// </summary>
public class ReadWriteLockCheck
{
    Dictionary<string, object> _dict = new Dictionary<string, object>();

    private ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);

    public void CreateByKey(string key)
    {
        _rwLock.EnterReadLock();
        try
        {
            if (!_dict.ContainsKey(key)) //Non blocking read - Check if exists
            {
                _rwLock.EnterWriteLock(); //Lock
                try
                {
                    _dict.Add(key, new object());
                }
                finally
                {
                    _rwLock.ExitWriteLock();
                }
            }
        }
        finally
        {
            _rwLock.ExitReadLock();
        }
    }

    public bool GetByKey(string key)
    {
        _rwLock.EnterWriteLock();
        try
        {
            if (_dict.ContainsKey(key)) //Non blocking read
            {
                return …
Run Code Online (Sandbox Code Playgroud)

.net c# multithreading locking readerwriterlockslim

3
推荐指数
1
解决办法
1404
查看次数

ReaderWriterLockSlim LockRecursionPolicy.SupportsRecursion DeadLock

我有一个数据库写入操作队列,由一个专用线程管理。我有很多线程可以随时从数据库读取数据。

我使用 ReaderWriterLockSlim 进行读/写访问控制。

我的问题是 - 为什么不推荐 LockRecursionPolicy.SupportsRecursion?MSDN 文档说:

不建议在新开发中使用递归,因为它会引入不必要的复杂性并使您的代码更容易出现死锁。

这里怎么会出现死锁呢?例如,如果我在已获取 WriteReadLock 时尝试调用 EnterReadLock(并且我处于 SupportsRecursion 策略下),则会出现异常...

c# multithreading readerwriterlockslim

3
推荐指数
1
解决办法
1911
查看次数

为什么使用ReaderWriterLockSlim不会使我的Dictionary线程安全?

我写了一小段代码,可以快速读取和写入多个线程的字典.我使用ReaderWriterLockSlim来保护代码,并且仍然收到了涉嫌尝试添加重复密钥的异常.

ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
Dictionary<int, int> _dict = new Dictionary<int, int>();

public SafeDictionaryTester()
{
    for (int i = 0; i < 7; i++)
    {
        _dict.Add(i, i);
    }
}

internal void Execute()
{
    for (int i = 7; i < 10000; i++)
    {
        if (i % 6 == 0)
            new Thread(new ThreadStart(delegate { Print(6); })).Start();
        else if (i % 5 == 0)
            new Thread(new ThreadStart(delegate { Print(5); })).Start();
        else if (i % 4 == 0)
            new Thread(new ThreadStart(delegate { …
Run Code Online (Sandbox Code Playgroud)

.net c# multithreading dictionary readerwriterlockslim

2
推荐指数
1
解决办法
1193
查看次数

ReaderWriterLockSlim和计时器

我对ReaderWriterLockSlim感到沮丧并且延迟了ExitWriteLock.为什么WriteLock在定时器中发布回调?

var _lock = new ReaderWriterLockSlim();
_lock.EnterWriteLock();
Assert.AreEqual(true, _lock.IsWriteLockHeld);   // good

System.Threading.Timer timer = new Timer(state =>
{
    _lock.ExitWriteLock(); //throws exception that lock is not held
}, null, 1, -1);

Thread.Sleep(1000);
Assert.AreEqual(false, _lock.IsWriteLockHeld);
Run Code Online (Sandbox Code Playgroud)

.net c# multithreading readerwriterlockslim

2
推荐指数
1
解决办法
122
查看次数

using(IDisposable)vs class field - 正确使用ReaderWriterLockSlim

FileWriter将由不同线程使用的类中,我当前使用a ReaderWriterLockSlim来防止当两个线程同时尝试写入文件时发生的错误,如下所示:

(1)

public class FileWriter
{
    private ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim();

    public void WriteToFile(string message)
    {
        try
        {
            this.readerWriterLock.EnterWriteLock();    
            // the writing happens here
        }
        finally
        {
            this.readerWriterLockSlim.ExitWriteLock();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

哪个确实有效.但在那之后,我读了那个ReaderWriterLockSlim工具IDisposable,所以我想知道是否

(2)

public class FileWriter
{
    public void WriteToFile(string message)
    {
        using (ReaderWriterLockSlim readerWriterLockSlim = new ReaderWriterLockSlim())
        {
            readerWriterLockSlim.EnterWriteLock();
            // the writing happens here
            readerWriterLockSlim.ExitWriteLock();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

将是"更好"的方法,是否会引入一些新的缺点.我的直觉告诉我,每次调用该方法我可能不应该创建一个新的ReaderWriterLockSlim,而只是一次(2) …

c# using-statement readerwriterlockslim

0
推荐指数
1
解决办法
64
查看次数