divinci
divinci

Reputation: 23139

C# Can Multiple Classes LOCK the Same Object using multiple References?

I want to make multiple instances of this class.

public class Worker
{
    private object _lockObject;
    private Thread _workerThread;
    private string _name;

    public Worker(object lockObject, string name)
    {
        _name = name;
        _lockObject = lockObject;
        _workerThread = new Thread(new ThreadStart(DoWork));
        _workerThread.Start();
    }
    private void DoWork()
    {
        while(true)
        {
            lock(_lockObject)
            {
                Console.WriteLine(_name + "Doing Work");
            }
        }
    }
}

If I pass the same lock object to multiple instances of the class, will a lock in one class instance result in the other class instance waiting on that lock to be free?

static void Main()
{
    private readonly object sharedLockObject = new object();
    Worker a = new Worker(sharedLockObject,"a");
    Worker b = new Worker(sharedLockObject,"b");
    Console.ReadLine();
}

I think that in the above case, Workers will never be : Console.WriteLine(_name + "Doing Work"); at the same time?

I just would like some confirmation, as I am unsure as to whether the lock() will lock the reference, or the object that is referenced.

Thanks!

Upvotes: 7

Views: 7105

Answers (4)

Matt Davis
Matt Davis

Reputation: 46034

What you are doing will work, but why not make the _lockObject member of the Worker class static? It will achieve the same effect but is more object-oriented.

public class Worker
{
    private static object _lockObject = new object();
    private Thread _workerThread;
    private string _name;

    public Worker(string name)
    {
        _name = name;
        _workerThread = new Thread(new ThreadStart(DoWork));
        _workerThread.Start();
    }
    private void DoWork()
    {
        while(true)
        {
            lock(_lockObject)
            {
                Console.WriteLine(_name + "Doing Work");
            }
        }
    }
}

EDIT: Oops! I didn't see @Darin Dimitrov's response, which is identical to what I've posted here. +1 to you, Darin.

Upvotes: 2

Yannick Motton
Yannick Motton

Reputation: 35971

The lock statement will mark the object instance, not the referencing variable.

lock(x) {
   ...
} 

Is precisely equivalent to:

System.Threading.Monitor.Enter(x);
try {
   ...
}
finally {
   System.Threading.Monitor.Exit(x);
}

where x is an object instance of a reference type.

So yes :-)

Upvotes: 4

Darin Dimitrov
Darin Dimitrov

Reputation: 1038780

I would recommend you not to pass a shared object that you use for locking or you could get into some nasty deadlocks. Use a static private member of the class to lock on:

public class Worker
{
    private static object _syncRoot = new object();
    private Thread _workerThread;
    private string _name;

    public Worker(string name)
    {
        _name = name;
        _workerThread = new Thread(new ThreadStart(DoWork));
        _workerThread.Start();
    }
    private void DoWork()
    {
        while(true)
        {
            lock(_syncRoot)
            {
                Console.WriteLine(_name + "Doing Work");
            }
        }
    }
}

Upvotes: 2

GraemeF
GraemeF

Reputation: 11457

Yes, object is a reference type so you are passing a reference to the same object, so that same object would be used by each Worker. The object is used for locking, not the reference.

Upvotes: 14

Related Questions