混淆在C#中的lock语句 [英] Confusion about the lock statement in C#

查看:188
本文介绍了混淆在C#中的lock语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是从MSDN:
锁定关键字确保一个线程不进入临界区$ C $的C ,而另一个线程在临界区

确实临界区必须是相同的临界区

还是意味着:
锁定关键字确保在另一个线程是由同一个对象把守的所有重要栏目一个线程不进入一个对象$ C $的C 把守的任何关键部分。 ?

 类节目
{
    静态无效的主要(字串[] args)
    {
        TestDifferentCriticalSections();        到Console.ReadLine();
    }    私有静态无效TestDifferentCriticalSections()
    {
        测试LO =新的测试();        螺纹T1 =新的Thread(()=>
        {
            lo.MethodA();
        });
        t1.Start();        螺纹T2 =新的Thread(()=>
        {
            lo.MethodB();
        });
        t2.Start();
    }
}公共类测试
{
    私人obj对象=新的对象();    公开测试()
    {}    公共无效方法a()
    {
        锁定(OBJ)
        {
            的for(int i = 0;我小于5;我++)
            {
                Thread.sleep代码(500);
                Console.WriteLine(A);
            }
        }
    }    公共无效的methodB()
    {
        锁定(OBJ)
        {
            的for(int i = 0;我小于5;我++)
            {
                Thread.sleep代码(500);
                Console.WriteLine(B);
            }
        }
    }
}


解决方案

现在的问题是混淆的措辞和答案迄今没有特别清楚无论是。让我改一下这个问题到几个问题:


  

(1)是否lock语句确保不超过一个线程处于锁定语句体在任一时刻


即可。例如:

 静态只读对象锁1 =新的对象();
静态只读对象锁2 =新的对象();
静态INT计数= 0;
静态对象M()
{
    INT C = Interlocked.Increment(REF计数器);
    返回C%2 == 0?锁1:锁2;
}...
锁定(M()){重要(); }

这是可能的两个线程都处于同时锁语句体,因为在两个不同的对象的锁语句锁。螺纹阿尔法可以调用M(),并得到锁1,然后线程测试可以调用M()并获得锁2。


  

(2)假设我锁语句总是锁定相同的对象上,并锁声明确保不超过一个活动线程处于锁的体在任一时刻


是的。如果你有:

 静态只读对象锁1 =新的对象();
...
锁(锁1){重要(); }

那么线程阿尔法可以采取锁和线程测试版将的的,直到锁进入锁体前可用。


  

(3)假设我有两个锁语句,并且两个锁定语句每次同一对象上锁,并一锁声明确保不超过一个活动线程处于任一锁体在任一时间?


是的。如果你有:

 静态只读对象锁1 =新的对象();
...
静态无效X()
{
    锁(锁1){CriticalX(); }
}
静态无效Y()
{
    锁(锁1){CriticalY(); }
}

那么,如果线程Alpha是在X和采取锁和线程测试是Y,那么线程测试版将的的,直到锁进入锁体前可用。


  

(4)你为什么要吓唬引号把主动?


要提请注意的事实,这是可能的的的线程在锁体。您可以使用 Monitor.Wait 法暂停线程是在锁体,并允许一个线程阻塞变得活跃,并输入锁体(或用于锁定同一对象的不同锁体)。等待的线程会保留在等待状态,直到脉冲。它是脉冲经过一段时间后,重新加入准备就绪队列的的,直到有在锁没有主动线程。接着它继续在它停止的点。

This is from MSDN: The lock keyword ensures that one thread does not enter a critical section of code while another thread is in the critical section.

Does a critical section have to be same as the critical section?

Or does it mean: The lock keyword ensures that one thread does not enter any critical section guarded by an object of code while another thread is in any critical section guarded by the same object. ?

    class Program
{
    static void Main(string[] args)
    {
        TestDifferentCriticalSections();

        Console.ReadLine();
    }

    private static void TestDifferentCriticalSections()
    {
        Test lo = new Test();

        Thread t1 = new Thread(() =>
        {
            lo.MethodA();
        });
        t1.Start();

        Thread t2 = new Thread(() =>
        {
            lo.MethodB();
        });
        t2.Start();
    }
}

public class Test
{
    private object obj = new object();

    public Test()
    { }

    public void MethodA()
    {
        lock (obj)
        {
            for (int i = 0; i < 5; i++)
            {
                Thread.Sleep(500);
                Console.WriteLine("A");
            }
        }
    }

    public void MethodB()
    {
        lock (obj)
        {
            for (int i = 0; i < 5; i++)
            {
                Thread.Sleep(500);
                Console.WriteLine("B");
            }
        }
    }
}

解决方案

The question is confusingly worded and the answers so far are not particularly clear either. Let me rephrase the question into several questions:

(1) Does the lock statement ensure that no more than one thread is in the body of the lock statement at any one time?

No. For example:

static readonly object lock1 = new object();
static readonly object lock2 = new object();
static int counter = 0;
static object M()
{
    int c = Interlocked.Increment(ref counter);
    return c % 2 == 0 ? lock1 : lock2;
}

...
lock(M()) { Critical(); }

It is possible for two threads to both be in the body of the lock statement at the same time, because the lock statement locks on two different objects. Thread Alpha can call M() and get lock1, and then thread Beta can call M() and get lock2.

(2) Assuming that my lock statement always locks on the same object, does a lock statement ensure that no more than one "active" thread is in the body of the lock at any one time?

Yes. If you have:

static readonly object lock1 = new object();
...
lock(lock1) { Critical(); }

then thread Alpha can take the lock, and thread Beta will block until the lock is available before entering the lock body.

(3) Assuming that I have two lock statements, and both lock statements lock on the same object every time, does a lock statement ensure that no more than one "active" thread is in the body of either lock at any one time?

Yes. If you have:

static readonly object lock1 = new object();
...
static void X() 
{
    lock(lock1) { CriticalX(); }
}
static void Y() 
{
    lock(lock1) { CriticalY(); }
}

then if thread Alpha is in X and takes the lock, and thread Beta is in Y, then thread Beta will block until the lock is available before entering the lock body.

(4) Why are you putting "active" in "scare quotes"?

To call attention to the fact that it is possible for a waiting thread to be in the lock body. You can use the Monitor.Wait method to "pause" a thread that is in a lock body, and allow a blocked thread to become active and enter that lock body (or a different lock body that locks the same object). The waiting thread will stay in its "waiting" state until pulsed. At some time after it is pulsed, it rejoins the "ready" queue and blocks until there is no "active" thread in the lock. It then resumes at the point where it left off.

这篇关于混淆在C#中的lock语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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