readerwriterlock允许在获取写锁定的同时进行读取? [英] readerwriterlock allowing reads while write lock is acquired?

查看:68
本文介绍了readerwriterlock允许在获取写锁定的同时进行读取?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个静态类,可以通过多个远程处理和应用程序线程的其他内部访问.该类功能的一部分是控制对各种文件的读/写访问,因此我在文件列表上实现了静态ReaderWriterLock.该项目使用.net framework 2.0作为客户需求的一部分.

但是,当我使用多个不同的客户端(通常我使用的是16个)对系统进行压力测试时,每个客户端都会执行大量的读写操作,然后会非常断断续续地进行,并且只有经过数小时甚至数天并且至少有500k +交易完成后系统崩溃.好的,所以我们有一个错误.

但是当我查看所有锁定事件的日志时,我发现发生了以下情况:

1:线程A直接获取写锁,检查IsWriterLock显示它为true.

2:即使线程A仍然具有写锁,线程B也会尝试获取读取器锁并成功

3:系统现在崩溃,堆栈跟踪现在显示了对readerwriterlock的空引用异常

此过程以前已经运行了数十万次,没有错误,我可以检查日志,看看在所有情况下,在所有情况下,读锁都被阻塞,直到退出写操作为止.我也曾尝试将readerwriterlock作为单例实现,但问题仍然存在

在此之前,有没有人见过这样的东西?

使用的Readerwriterlock实现的精简版本如下所示:

private const int readwriterlocktimeoutms = 5000;
    private static ReaderWriterLock readerWriterLock = new ReaderWriterLock();


    // this method will be called by thread A
    public static void MethodA()
    {
        // bool to indicate that we have the lock
        bool IsTaken = false;

        try
        {                
            // get the lock
            readerWriterLock.AcquireWriterLock(readwriterlocktimeoutms);

            // log that we have the lock for debug
            // Logger.LogInfo("MethodA: acquired write lock; writer lock held {0}; reader lock held {1}", readerWriterLock.IsWriterLockHeld.ToString(),readerWriterLock.IsReaderLockHeld.ToString(), );

            // mark that we have taken the lock
            IsTaken = true;
        }
        catch(Exception e)
        {
            throw new Exception(string.Format("Error getting lock {0} {1}", e.Message, Environment.StackTrace));
        }

        try
        {
           // do some work
        }
        finally
        {
            if (IsTaken)
            {
                readerWriterLock.ReleaseWriterLock();
            }
        }

    }

    // this method will be called by thread B
    public static void MethodB()
    {
        // bool to indicate that we have the lock
        bool IsTaken = false;

        try
        {
            // get the lock
            readerWriterLock.AcquireReaderLock(readwriterlocktimeoutms);

            // log that we have the lock for debug
            // Logger.LogInfo("MethodB: acquired read lock; writer lock held {0}; reader lock held {1}", readerWriterLock.IsWriterLockHeld.ToString(),readerWriterLock.IsReaderLockHeld.ToString(), );

            // mark that we have taken the lock
            IsTaken = true;
        }
        catch (Exception e)
        {
            throw new Exception(string.Format("Error getting lock {0} {1}", e.Message, Environment.StackTrace));
        }

        try
        {
           // do some work
        }
        finally
        {
            if (IsTaken)
            {
                readerWriterLock.ReleaseReaderLock();
            }
        }
    }

enter code here

解决方案

@All终于可以解决此问题. @Yannick,您的目标正确无误...

如果MSDN表示不可能同时拥有读写器锁.

今天,我从Microsoft那里得到确认,如果在多处理器系统上负载很重(注意:我永远不能仅在Intel的AMD系统上重现此问题),则ReaderWriterLock类对象可能会损坏,这有可能如果在任何给定阶段的作家数量增加,因为可以在队列中进行备份,则数量会增加.

在过去的两周里,我一直在使用.Net 3.5 ReaderWriterLockSlim类运行,并且没有遇到此问题,这与Microsoft确认的问题有关,即ReaderReaderLockslim类与肥胖的ReaderWriterLock没有相同的损坏风险.课.

I have a static class which is accessed by multiple remoting and other internal to the application threads. Part of the functionality of this class is controlling read/write access to various files, so I've implemented a static ReaderWriterLock on the list of files. The project uses the .net framework 2.0 as part of the customer requirements.

However when I stress test the system using a number of different clients (generally I'm using 16) each performing a large amount of reads and writes then very intermittently and only after several hours or even days have passed with at least 500k+ transactions completed the system crashes. Ok so we got a bug..

But when I check the logs of all locking events I can see that the following has happened:

1: Thread A acquires a write lock directly, checking IsWriterLock shows it to be true.

2: Thread B tries to acquire a reader lock and succeeds even though Thread A still has the write lock

3: System now crashes, stack trace now shows a null reference exception to the readerwriterlock

This process has been run several hundred thousand times previously with no errors and I can check the logs and see that the read lock was blocked in all cases previously until the write had exited. I have also tried implementing the readerwriterlock as a singleton but the issue still occurs

Has anybody ever seen anything like this before ??

A slimed down version of the readerwriterlock implementation used is shown below:

private const int readwriterlocktimeoutms = 5000;
    private static ReaderWriterLock readerWriterLock = new ReaderWriterLock();


    // this method will be called by thread A
    public static void MethodA()
    {
        // bool to indicate that we have the lock
        bool IsTaken = false;

        try
        {                
            // get the lock
            readerWriterLock.AcquireWriterLock(readwriterlocktimeoutms);

            // log that we have the lock for debug
            // Logger.LogInfo("MethodA: acquired write lock; writer lock held {0}; reader lock held {1}", readerWriterLock.IsWriterLockHeld.ToString(),readerWriterLock.IsReaderLockHeld.ToString(), );

            // mark that we have taken the lock
            IsTaken = true;
        }
        catch(Exception e)
        {
            throw new Exception(string.Format("Error getting lock {0} {1}", e.Message, Environment.StackTrace));
        }

        try
        {
           // do some work
        }
        finally
        {
            if (IsTaken)
            {
                readerWriterLock.ReleaseWriterLock();
            }
        }

    }

    // this method will be called by thread B
    public static void MethodB()
    {
        // bool to indicate that we have the lock
        bool IsTaken = false;

        try
        {
            // get the lock
            readerWriterLock.AcquireReaderLock(readwriterlocktimeoutms);

            // log that we have the lock for debug
            // Logger.LogInfo("MethodB: acquired read lock; writer lock held {0}; reader lock held {1}", readerWriterLock.IsWriterLockHeld.ToString(),readerWriterLock.IsReaderLockHeld.ToString(), );

            // mark that we have taken the lock
            IsTaken = true;
        }
        catch (Exception e)
        {
            throw new Exception(string.Format("Error getting lock {0} {1}", e.Message, Environment.StackTrace));
        }

        try
        {
           // do some work
        }
        finally
        {
            if (IsTaken)
            {
                readerWriterLock.ReleaseReaderLock();
            }
        }
    }

enter code here

解决方案

@All finally have a solution to this problem. @Yannick you were on the right track...

If MSDN says that it's impossible to have reader and writer lock held at same time.

Today I got confirmation from microsoft that in cases of very heavy load on multiprocessor systems (note: I could never reproduce this problem on an AMD system only on Intel) its possible for ReaderWriterLock class objects to become corrupted, the risk of this is increased if the numer of writers at any given stage grows as these can backup in the queue.

For the last two weeks I've been running using the .Net 3.5 ReaderWriterLockSlim class and have not encountered the issue, which corresponds to what Microsoft have confirmed that the readerwriterlockslim class does not have the same risk of corruption as the fat ReaderWriterLock class.

这篇关于readerwriterlock允许在获取写锁定的同时进行读取?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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