首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Monitor.Pulse()没有作用

Monitor.Pulse()没有作用
EN

Stack Overflow用户
提问于 2012-07-24 10:10:55
回答 2查看 159关注 0票数 0

这是我的代码片段。我想,一个线程应该可以工作,而不需要等待上一个线程完成。但我意识到所有线程都是串联启动的,我的脉冲调用对它们的工作方式没有任何影响。

代码语言:javascript
复制
class A
{
    string path = "file.xml";
    static public object _lock = new object();
    static private int accessCounter = 0;

    public List<T> GetItems()
    {
        List<T> result = null;
        lock (_lock)
        {

            while (accessCounter < 0)
                Monitor.Wait(_lock);
            accessCounter++;
            Thread.Sleep(1000);

            Monitor.Pulse(_lock);
            Thread.Sleep(1000);

            using (Stream stream = File.OpenRead(path))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(List<T>), new Type[] { typeof(T) });
                result = (List<T>)serializer.Deserialize(stream);
            }
            accessCounter--;
            Monitor.Pulse(_lock);
        }
        return result;
    }
    public void AddItem(T item)
    {
      lock(_lock){if (accessCounter!=0) Monitor.Wait(_lock);
      accessCounter = -1;
      //some writing ooperations
      accessCounter = 0;
       }
    }
}

我知道,如果条件在目前的情况下是无用的,因为它总是正确的。更重要的是,它们应该同时工作,但不起作用。

编辑:此代码以下列方式从不同线程调用:

代码语言:javascript
复制
.....
A a = new A();
var list = a.GetItems();
.....

应该是某种写作/阅读障碍。因此,如果线程想要读取并且其他线程已经在读取文件,那么它不必等待其他线程。如果其他线程捕获了*_lock*,则所有读取线程都需要挂起。

EN

回答 2

Stack Overflow用户

发布于 2012-07-24 10:15:33

您的访问柜台检查错了。它应该检查是否大于,而不小于。

代码语言:javascript
复制
while (accessCounter > 0)
    Monitor.Wait(_lock);

但是,您的代码似乎有点奇怪。访问计数器检查发生在锁定在_lock上的关键线程中,因此无论如何都不可能有超过一个线程正在执行此代码。这就是为什么您的代码不能同时执行的原因。

另外,请注意,Monitor.Wait 会释放当前线程持有的锁--它不会等待锁变得空闲。

票数 1
EN

Stack Overflow用户

发布于 2012-07-24 12:10:47

该框架已经提供了一种锁定机制(实际上是两种),它应该做您想做的事情(即允许许多同时阅读的读者,但写作是排他性的(同时没有其他读者或作者)-- ReaderWriterLock和ReaderWriterLockSlim。

可以将代码修改为以下内容,以利用ReaderWriterLockSlim:

代码语言:javascript
复制
class A
{
    private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
    string path = "file.xml";
    static public object _lock = new object();
    static private int accessCounter = 0;

    public List<T> GetItems()
    {
        _lock.EnterReadLock();
        try
        {
            using (Stream stream = File.OpenRead(path))
            {
                var serializer = new XmlSerializer(typeof(List<T>), new[] { typeof(T) });
                return (List<T>)serializer.Deserialize(stream);
            }
        }
        finally
        {
            _lock.ExitReadLock();
        }
    }

    public void AddItem(T item)
    {
        _lock.EnterWriteLock();
        try
        {
            // Some writing operations
        }
        finally
        {
            _lock.ExitWriteLock();
        }
    }
}

同样值得注意的是,这个方法会泄漏内存,因为每次使用XmlSerializer(Type)XmlSerializer(Type, String)以外的构造函数创建一个新的XmlSerializer(Type, String)。这将导致每次生成和加载一个新的XML序列化程序集,并且这些程序集永远不会被释放。您需要切换到使用上述两个构造函数之一,或者缓存XmlSerializer实例(可能是由typeof(T)键控),这样就不会泄漏内存。

有关更多信息,请参见此处的“动态生成程序集”部分:XmlSerializer文档

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

https://stackoverflow.com/questions/11628625

复制
相关文章

相似问题

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