C#锁定关键字的用法

本文关键字:用法 关键字 锁定 | 更新日期: 2023-09-27 17:58:02

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

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

案例I>线程1和线程2同时尝试调用PrintOne。由于PrintOne由实例锁保护,因此在任何时候一个线程只能进入SectionOne。

这是正确的吗

案例II>线程1和线程2同时尝试调用PrintOne和PrintTwo(即Thread1调用PrintOne,Thread2调用PrintTwo)由于两种打印方法在任何时候都由相同的实例锁保护,只有一个线程可以独占访问SectionOne或SectionTwo,但不能同时访问这两个线程。

这是正确的吗

C#锁定关键字的用法

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 提出的好观点

"螺纹安全性"也假定为上下文例如,我可以您的文件打开代码,以及使用静态锁生成异常-只是接受另一个应用程序领域因此,建议OP应使用系统范围的Mutex类或诸如此类的事情。因此静态情况只是推断为实例一。

案例一:检查✓

案例二:检查✓

不要忘记,锁定只是线程同步的一种方式。有关其他userfull方法,请阅读:线程同步

直接来自MSDN示例:

public class TestThreading
{
    private System.Object lockThis = new System.Object();
    public void Process()
    {    
        lock (lockThis)
        {
            // Access thread-sensitive resources.
        }
    }    
}

是和是。案例是正确的。

您的理解是100%正确的。因此,例如,如果您想允许分别进入这两个方法,您就需要有两个锁。

是的,你在这两方面都是正确的。

以下是基本的(或多或少)

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++;
        }
     }
}

基于此,如果您正在访问实例数据,则您的代码是可以的,但如果您正在修改静态数据

,则代码是不安全的