首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ReaderWriterLock.UpgradeToWriterLock不会在超时结束后抛出异常吗?

ReaderWriterLock.UpgradeToWriterLock不会在超时结束后抛出异常吗?
EN

Stack Overflow用户
提问于 2014-05-23 17:28:45
回答 1查看 544关注 0票数 1

在编写单元测试时,我偶然发现了ReaderWriterLock中一个非常奇怪的问题。我尝试测试UpgradeToWriterLock方法,将超时选项设置为50毫秒。

在主线程上,我使用读取器锁,然后启动许多任务。在这些任务中,我也使用读取器锁定,然后尝试升级到编写器,并使用超时。当主线程持有读锁时,每一个线程都会失败。由于超时时间是50毫秒,任务应该抛出一个超时异常并完成。如果我开始超过10项任务,他们不会。他们会被困在UpgradeToWriterLock上。

有人能解释一下吗?下面的全部源代码。

代码语言:javascript
复制
    [TestMethod]
    public void UpgradeLockFailTest()
    {
        // strangely when more than 10 threads then it gets stuck on UpgradeToWriterLock regardless of the timeout
        const int THREADS_COUNT = 20;
        // 50 milliseconds
        const int TIMEOUT = 50;

        // create the main reader writer lock
        ReaderWriterLock rwl = new ReaderWriterLock();

        // acquire the reader lock on the main thread
        rwl.AcquireReaderLock(TIMEOUT);

        // create and start all the tasks
        Task[] tasks = new Task[THREADS_COUNT];
        for (int i = 0; i < THREADS_COUNT; i++)
        {
            tasks[i] = Task.Factory.StartNew(() =>
            {
                try
                {
                    // acquire the reader lock on the worker thread
                    rwl.AcquireReaderLock(TIMEOUT);

                    // acquire the writer lock on the worker thread 
                    rwl.UpgradeToWriterLock(TIMEOUT); // <-- GETS STUCK HERE AND DOESN'T RESPECT TIMEOUT

                }
                finally
                {
                    rwl.ReleaseLock();
                }

            });
        }

        // should be enough for all the tasks to be created
        Thread.Sleep(2000);

        try
        {
            // wait for all tasks
            Task.WaitAll(tasks); // <-- GETS STUCK HERE BECAUSE THE TASKS ARE STUCK ON UpgradeToWriterLock
        }
        catch (AggregateException ae)
        {
            Assert.AreEqual(THREADS_COUNT, ae.InnerExceptions.Count);
        }

        // release all the locks on the main thread
        rwl.ReleaseLock();
    }

有趣的是,如果我在等待任务之前释放主线程读取器锁,一切都按预期工作。引发的超时异常的正确数目。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-23 18:25:39

你确定他们都被困住了,而不仅仅是最后一个?

来自 documentation

在调用方法的线程重新获取读取器锁之前,不会抛出超时异常。如果没有其他线程在等待写入器锁,则立即发生这种情况。但是,,如果另一个线程排队等待写入器锁,则调用UpgradeToWriterLock方法的线程不能重新获取读取器锁,直到所有当前读取器释放了它们的锁,并且有一个线程获得并释放了写入器锁。即使请求写入器锁的另一个线程在当前线程调用UpgradeToWriterLock方法之后请求它,也是如此。

注意抛出超时异常必须发生的多个条件。“如果另一个线程排队等待写入器锁,调用UpgradeToWriterLock方法的线程不能重新获取读取器锁并抛出异常,直到”:

  1. 所有当前的读者都释放了他们的锁。
  2. 一个线程已经获得并释放了写入器锁。

对于试图升级的最后一个线程,您永远不允许出现这些情况,因此您可以在UpgradeToWriterLock上永远等待,所以WaitAll也会永远等待。如果你的主线程在等待前也试图升级,我想你会没事的。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23835189

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档