使用C#lock关键字

q09*_*987 8 c# multithreading locking

我发布了对C#lock的理解如下,请帮助我验证我是否正确.

public class TestLock
{
    private object threadLock = new object();
    ...
    public void PrintOne()
    {
        lock (threadLock)
        {
            // SectionOne
        }
    }

    public void PrintTwo()
    {
        lock (threadLock)
        {
            // SectionTwo
        }
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

案例I> Thread1和Thread2同时尝试调用PrintOne.由于PrintOne受到实例锁的保护,因此任何时候只有一个线程可以独占进入SectionOne.

它是否正确?

案例II> Thread1和Thread2分别同时尝试调用PrintOne和PrintTwo(即Thread1调用PrintOne和Thread2调用PrintTwo)由于两个打印方法都被同一个实例锁保护,因此任何时候只有一个线程可以独占访问SectionOne或SectionTwo ,但不是两个.

它是否正确?

ole*_*sii 6

当所有线程使用同一个类实例时,1和2才为.如果他们使用不同的实例,则两种情况都是错误的

样品

public class TestLock
{
    private  object threadLock = new object();

    public void PrintOne()
    {
        lock (threadLock)
        {
            Console.WriteLine("One");
            var f = File.OpenWrite(@"C:\temp\file.txt"); //same static resource
            f.Close();
        }
    }

    public void PrintTwo()
    {
        lock (threadLock)
        {
            Console.WriteLine("Two");
            var f = File.OpenWrite(@"C:\temp\file.txt"); //same static resource
            f.Close();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并测试代码

static void Main(string[] args)
{
    int caseNumber = 100;

    var threads = new Thread[caseNumber];
    for (int i = 0; i < caseNumber; i++)
    {
        var t = new Thread(() =>
                                {
                                    //create new instance
                                    var testLock = new TestLock();
                                    //for this instance we safe
                                    testLock.PrintOne();
                                    testLock.PrintTwo();
                                });
        t.Start();
        //once created more than one thread, we are unsafe
    }
}
Run Code Online (Sandbox Code Playgroud)

一种可能的解决方案是向锁定对象声明和使用它的方法添加一个static关键字.

private  static object threadLock = new object();
Run Code Online (Sandbox Code Playgroud)

更新 konrad.kruczynski提出的好点

......"线程安全"也是从上下文中假设的.例如,我可以使用您的文件打开代码并使用静态锁生成异常 - 只需要另一个应用程序域.因此建议OP应该使用系统范围的Mutex类或类似的那样.因此静态情况只是推断为实例一.

  • 锁定性能与锁定的争用程度直接相关.所以你真的不应该使用静态锁,除非你正在修改静态数据,如果你使用的是静态锁,除了保护静态数据之外你不应该使用它. (3认同)

kon*_*ski 1

是的,是的。案例是正确的。