C#锁定关键字

问题描述

我对C#锁的理解如下,请帮助我验证是否正确。
public class TestLock
{
    private object threadLock = new object();
    ...
    public void PrintOne()
    {
        lock (threadLock)
        {
            // SectionOne
        }
    }

    public void PrintTwo()
    {
        lock (threadLock)
        {
            // SectionTwo
        }
    }
    ...
}
情况I> Thread1和Thread2同时尝试调用PrintOne。 由于PrintOne受到实例锁的保护,因此在任何时候都只能 一个线程可以专门进入SectionOne。 它是否正确? 情况二>线程1和线程2同时尝试调用PrintOne和PrintTwo 分别(即Thread1调用PrintOne和Thread2调用PrintTwo) 由于两种打印方法均由同一实例锁保护,因此, 只有一个线程可以独占访问SectionOne或SectionTwo,但不能同时访问这两个线程。 它是否正确?     

解决方法

        仅当所有线程都使用该类的相同实例时,1和2才为true。如果他们使用不同的实例,则两种情况都为假 样品
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();
        }
    }
}
和测试代码
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
    }
}
一种可能的解决方案是在锁定对象声明和使用它的方法中添加一个静态关键字。
private  static object threadLock = new object();
更新 konrad.kruczynski提出的要点   ... \“线程安全\”也假定为   上下文。例如,我可以   您的文件打开代码以及   使用静态锁生成异常-   只是接受另一个申请   域。因此建议   应该使用系统范围内的Mutex类或   那样因此静态情况   只是被推论为实例之一。     ,        是的,是的。情况是正确的。     ,        您的理解是100%正确的。因此,例如,如果您想允许分别进入这两种方法,则需要两个锁。     ,        案例一:检查✓ 情况二:检查✓ 不要忘记,锁定只是线程同步的一种方法。有关其他用户完整方法,请阅读:线程同步 直接来自MSDN示例:
public class TestThreading
{
    private System.Object lockThis = new System.Object();

    public void Process()
    {    
        lock (lockThis)
        {
            // Access thread-sensitive resources.
        }
    }    
}
    ,        是的,您在两个方面都是正确的。     ,        这是基本知识(或多或少) 1)对实例数据使用实例锁
public class InstanceOnlyClass{
    private int callCount;
    private object lockObject = new object();

    public void CallMe()
    {
        lock(lockObject)
        {
            callCount++;
        }
     }
}
2)对静态数据使用静态锁
public class StaticOnlyClass{
    private int createdObjects;
    private static object staticLockObject = new object();

    public StaticOnlyClass()
    {
        lock(staticLockObject)
        {
            createdObjects++;
        }
    }
}
3)如果您要保护静态和实例数据,请使用单独的静态和实例锁
public class StaticAndInstanceClass{
    private int createdObjects;

    private static object staticLockObject = new object();

    private int callCount;

    private object lockObject = new object();

    public StaticAndInstanceClass()
    {
        lock(staticLockObject)
        {
            createdObjects++;
        }
    }

    public void CallMe()
    {
        lock(lockObject)
        {
            callCount++;
        }
     }
}
基于此,如果您访问实例数据,则代码很好,但是如果您修改静态数据,则代码不安全