在什么条件下可以一个线程进入一个锁(监视器)区不止一次同时? [英] Under what conditions can a thread enter a lock (Monitor) region more than once concurrently?

查看:120
本文介绍了在什么条件下可以一个线程进入一个锁(监视器)区不止一次同时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(修订问题):到目前为止,答案都包括一个单独的线程重新进入锁定区域线,通过像递归,在那里你可以跟踪单个线程的步骤进入锁两次。但有可能以某种方式,为单个线程(可能是从线程池,也许作为计时器事件或异步事件或线程睡觉和结果被唤醒/在code分体的一些其它块重复使用),以某种方式催生在两个不同的地方彼此独立,因此,运行到锁定重入的问题,当显影剂没有通过简单地读取自己code期待什么?

在ThreadPool类备注(点击此处 )备注似乎表明,睡眠线程的,应当他们不使用的睡眠重复使用,或以其他方式浪费掉了。

但Monitor.Enter参考页面上(点击此处)他们说的是合法的同一个线程调用输入多于一次不堵。的所以我想一定有什么东西我应该小心避免。它是什么?这怎么的可能的针对单一线程进入同一锁定区域两次?

假设你有一定的锁定区域,它接受一个不幸长的时间。这可能是现实的,例如,如果你访问已被调出一些内存(或其他)。在锁定区域中的线程可能会去睡觉什么的。是否在同一个线程有资格运行更code,这可能会不小心踏入同一条锁定区域?以下不,在我的测试,得到相同的线程的多个实例运行在同一个锁定区域。

那么,如何产生的问题?究竟你需要小心避免?

  MyClass类
{
    私有对象myLockObject;
    公共MyClass的()
    {
        this.myLockObject =新的对象();
        INT [] myIntArray =新INT [100]; //只要创建了一堆东西,所以我可以很容易地发射一束平行的东西
        Array.Clear(myIntArray,0,myIntArray.Length); //只要创建了一堆东西,所以我可以很容易地发射一束平行的东西
        Parallel.ForEach< INT>(myIntArray,I => MyParallelMethod());
    }
    私人无效MyParallelMethod()
    {
        锁定(this.myLockObject)
        {
            Console.Error.WriteLine(线程标识+ Thread.CurrentThread.ManagedThreadId.ToString()+出发......);
            Thread.sleep代码(100);
            Console.Error.WriteLine(线程标识+ Thread.CurrentThread.ManagedThreadId.ToString()+完了。);
        }
    }
}
 

解决方案

线程池线程不能在其他地方重复使用,只是因为他们睡觉去了;他们需要完成他们重新使用之前。这是需要很长时间的锁定区域线程​​没有资格以控制其他独立点运行多个code。体验锁重入的唯一方法是通过递归或执行锁,重新进入锁里面的方法或代表。

(question revised): So far, the answers all include a single thread re-entering the lock region linearly, through things like recursion, where you can trace the steps of a single thread entering the lock twice. But is it possible somehow, for a single thread (perhaps from the ThreadPool, perhaps as a result of timer events or async events or a thread going to sleep and being awaken/reused in some other chunk of code separately) to somehow be spawned in two different places independently of each other, and hence, run into the lock re-entrance problem when the developer didn't expect it by simply reading their own code?

In the ThreadPool Class Remarks (click here) the Remarks seem to suggest that sleeping threads should be reused when they're not in use, or otherwise wasted by sleeping.

But on the Monitor.Enter reference page (click here) they say "It is legal for the same thread to invoke Enter more than once without it blocking." So I figure there must be something I'm supposed to be careful to avoid. What is it? How is it even possible for a single thread to enter the same lock region twice?

Suppose you have some lock region that takes an unfortunately long time. This might be realistic, for example, if you access some memory that has been paged out (or whatever.) The thread in the locked region might go to sleep or something. Does the same thread become eligible to run more code, which might accidentally step into the same lock region? The following does NOT, in my testing, get multiple instances of the same thread to run into the same lock region.

So how does one produce the problem? What exactly do you need to be careful to avoid?

class myClass
{
    private object myLockObject;
    public myClass()
    {
        this.myLockObject = new object();
        int[] myIntArray = new int[100];               // Just create a bunch of things so I may easily launch a bunch of Parallel things
        Array.Clear(myIntArray, 0, myIntArray.Length); // Just create a bunch of things so I may easily launch a bunch of Parallel things
        Parallel.ForEach<int>(myIntArray, i => MyParallelMethod());
    }
    private void MyParallelMethod()
    {
        lock (this.myLockObject)
        {
            Console.Error.WriteLine("ThreadId " + Thread.CurrentThread.ManagedThreadId.ToString() + " starting...");
            Thread.Sleep(100);
            Console.Error.WriteLine("ThreadId " + Thread.CurrentThread.ManagedThreadId.ToString() + " finished.");
        }
    }
}

解决方案

ThreadPool threads cannot be reused elsewhere just because they went to sleep; they need to finish before they're reused. A thread that is taking a long time in a lock region does not become eligible to run more code at some other independent point of control. The only way to experience lock re-entry is by recursion or executing methods or delegates inside a lock that re-enter the lock.

这篇关于在什么条件下可以一个线程进入一个锁(监视器)区不止一次同时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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