开发者

Usage of the C# lock keyword

I post my understanding of C# lock as follows, please help me validate whether or not I get it right.

public class TestLock
{
    pr开发者_开发技巧ivate object threadLock = new object();
    ...
    public void PrintOne()
    {
        lock (threadLock)
        {
            // SectionOne
        }
    }

    public void PrintTwo()
    {
        lock (threadLock)
        {
            // SectionTwo
        }
    }
    ...
}

Case I> Thread1 and Thread2 simultaneously try to call PrintOne. Since PrintOne is guarded by the instance lock, at any time, only one thread can exclusively enter the SectionOne.

Is this correct?

Case II> Thread1 and Thread2 simultaneously try to call PrintOne and PrintTwo respectively (i.e. Thread1 calls PrintOne and Thread2 calls PrintTwo) Since two print methods are guarded by the same instance lock, at any time, only one thread can exclusively access either SectionOne or SectionTwo, but NOT both.

Is this correct?


1 and 2 are true only if all your threads use the same instance of the class. If they use different instances, then both cases are false

Sample

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();
        }
    }
}

And testing code

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

One of the possible solutions is to add a static keyword to the locking object declaration and methods that use it.

private  static object threadLock = new object();

UPDATE Good point made by konrad.kruczynski

..."thread safety" is also assumed from context. For example, I could take your file opening code and also generate exception with static lock - just taking another application domain. And therefore propose that OP should use system-wide Mutex class or sth like that. Therefore static case is just inferred as the instance one.


Case I: Check ✓

Case II: Check ✓

Don't forget that locking is only one way of thread synchronization. For other userfull methods, read: Thread Synchronization

Straight from MSDN sample:

public class TestThreading
{
    private System.Object lockThis = new System.Object();

    public void Process()
    {    
        lock (lockThis)
        {
            // Access thread-sensitive resources.
        }
    }    
}


Yes and yes. Cases are correct.


Your understanding is 100% correct. So if, for instance, you wanted to allow entry into the two methods separately you would want to have two locks.


Yes, you're correct in both counts.


here are the basics (more or less)

1) use instance locks for instance data

public class InstanceOnlyClass{
    private int callCount;
    private object lockObject = new object();

    public void CallMe()
    {
        lock(lockObject)
        {
            callCount++;
        }
     }
}

2) use static locks for static data

public class StaticOnlyClass{
    private int createdObjects;
    private static object staticLockObject = new object();

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

3) if you are protecting static and instance data use separate static and instance locks

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

based on this your code is fine if you are accessing instance data but unsafe if you are modifying static data

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜