John Tan
John Tan

Reputation: 1385

Making class fields thread-safe

Say I have a List of values that I accessed by different threads. So I make it thread safe by doing something like this:

private static object syncObject;
syncObject = new Object();

public List<double> MyList
{
    get
    {
        lock(syncObject) { return myList;}
    }   
    set
    {
        lock(syncObject) { myList = value;}
    }
}

If in one of my functions, I need to access the Count attribute of the List, it may not be thread safe anymore. So how do I write it such that even when accessing the attributes, it will be thread safe?

Upvotes: 2

Views: 3963

Answers (4)

Kapoor
Kapoor

Reputation: 1428

I agree that its best never to reinvent the wheel, but just incase you are working on an old .Net version like 2.0 where System.Collections.Concurrent is unavailable, you may follow a different paradigm -

So you never expose the list to the outside world but only the operations & these operations can be made mutually exclusive by adding locks. For example

public void AddToCollection(double value)
{   
    lock(syncObject)
    {
        myList.Add(value);
    }    
}

public int Count
{
   lock (syncObject)
   {
      myList.Count;
   }
}

Upvotes: 0

Stefan Turcanu
Stefan Turcanu

Reputation: 924

Like Willem van Rumpt said, you just synchronized the access to that specific property, not made it thread safe. To not reinvent the wheel, you can use the collections from System.Collections.Concurrent (https://msdn.microsoft.com/en-us/library/dd267312(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1)

Another more viable option would be to use an immutable list. Unfortunately, afaik .Net doesn't offer too much here. The only implementation I know about is in Microsoft.FSharp.Collections. The list in this namespace is an immutable singly-linked list. (although I haven't used it from C#).

UPDATE: As Matías Fidemraizer noted, there is the System.Collections.Immutable nuget package available for .net 4.5 and above that contains implementations for multiple immutable collections. Thank you!

Upvotes: 4

larsbj1988
larsbj1988

Reputation: 16

You are not doing this right. In your example the lock is released when the get property returns the list.

Instead you could encapsulate the list in a class and make the list private. In that class you can have public methods that manipulates the list and uses the lock like this:

public void A()
{
    lock (syncObject)
    {
    // do something here
    }
}

This will ensure only one thread can work on the list at a time.

Upvotes: 0

Mat&#237;as Fidemraizer
Mat&#237;as Fidemraizer

Reputation: 64933

In order to implement your code with thread-safety, you need to lock the collection until you don't need it anymore in some part of your code.

For example:

lock(syncObject)
{
     MyList.Add(23.99);
}

Therefore, whenever some other part of your code tries to acquire a lock, it will wait until the other thread exists the critical/synchronized code.

Upvotes: 0

Related Questions