Reputation: 1385
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
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
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
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
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