使用C#lock关键字

我发布了对C#lock的理解如下,请帮我validation是否正确。

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。

它是否正确?

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

它是否正确?

当所有线程使用同一个类实例时,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(); } } } 

并测试代码

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

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

 private static object threadLock = new object(); 

更新 konrad.kruczynski提出的好点

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

是的,是的。 案件是正确的。

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

案例I:检查✓

案例二:检查✓

不要忘记锁定只是线程同步的一种方式。 对于其他用户满意的方法,请阅读: 线程同步

直接来自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++; } } } 

基于此,如果您正在访问实例数据,那么您的代码就可以了,但如果要修改静态数据则不安全