Multi-Threading Question - adding an Element to a static List - c#

Okay, newbie multi-threading question:
I have a Singleton class. The class has a Static List and essentially works like this:
class MyClass {
private static MyClass _instance;
private static List<string> _list;
private static bool IsRecording;
public static void StartRecording() {
_list = new List<string>();
IsRecording = true;
}
public static IEnumerable<string> StopRecording() {
IsRecording = false;
return new List<string>(_list).AsReadOnly();
}
public MyClass GetInstance(){
}
public void DoSomething(){
if(IsRecording) _list.Add("Something");
}
}
Basically a user can call StartRecording() to initialize a List and then all calls to an instance-method may add stuff to the list. However, multiple threads may hold an instance to MyClass, so multiple threads may add entries to the list.
However, both list creation and reading are single operations, so the usual Reader-Writer Problem in multi-threading situations does not apply. The only problem I could see is the insertion order being weird, but that is not a problem.
Can I leave the code as-is, or do I need to take any precautions for multi-threading? I should add that in the real application this is not a List of strings but a List of Custom Objects (so the code is _list.Add(new Object(somedata))), but these objects only hold data, no code besides a call to DateTime.Now.
Edit: Clarifications following some answers: DoSomething cannot be static (the class here is abbreviated, there is a lot of stuff going on that is using instance-variables, but these created by the constructor and then only read).
Is it good enough to do
lock(_list){
_list.Add(something);
}
and
lock(_list){
return new List<string>(_list).AsReadOnly();
}
or do I need some deeper magic?

You certainly must lock the _list. And since you are creating multiple instances for _list you can not lock on _list itself but you should use something like:
private static object _listLock = new object();
As an aside, to follow a few best practices:
DoSomething(), as shown, can be static and so it should be.
for Library classes the recommended pattern is to make static members thread-safe, that would apply to StartRecording(), StopRecording() and DoSomething().
I would also make StopRecording() set _list = null and check it for null in DoSomething().
And before you ask, all this takes so little time that there really are no performance reasons not to do it.

You need to lock the list if multiple threads are adding to it.
A few observations...
Maybe there's a reason not to, but I would suggest making the class static and hence all of its members static. There's no real reason, at least from what you've shown, to require clients of MyClass to call the GetInstance() method just so they can call an instance method, DoSomething() in this case.
I don't see what prevents someone from calling the StartRecording() method multiple times. You might consider putting a check in there so that if it is already recording you don't create a new list, pulling the rug out from everyone's feet.
Finally, when you lock the list, don't do it like this:
static object _sync = new object();
lock(_sync){
_list.Add(new object(somedata));
}
Minimize the amount of time spent inside the lock by moving the new object creation outside of the lock.
static object _sync = new object();
object data = new object(somedata);
lock(_sync){
_list.Add(data);
}
EDIT
You said that DoSomething() cannot be static, but I bet it can. You can still use an object of MyClass inside DoSomething() for any instance-related stuff you have to do. But from a programming usability perspective, don't require the users to MyClass to call GetInstance() first. Consider this:
class MyClass {
private static MyClass _instance;
private static List<string> _list;
private static bool IsRecording;
public static void StartRecording()
{
_list = new List<string>();
IsRecording = true;
}
public static IEnumerable<string> StopRecording()
{
IsRecording = false;
return new List<string>(_list).AsReadOnly();
}
private static MyClass GetInstance() // make this private, not public
{ return _instance; }
public static void DoSomething()
{
// use inst internally to the function to get access to instance variables
MyClass inst = GetInstance();
}
}
Doing this, the users of MyClass can go from
MyClass.GetInstance().DoSomething();
to
MyClass.DoSomething();

.NET collections are not fully thread-safe. From MSDN: "Multiple readers can read the collection with confidence; however, any modification to the collection produces undefined results for all threads that access the collection, including the reader threads." You can follow the suggestions on that MSDN page to make your accesses thread-safe.
One problem that you would probably run into with your current code is if StopRecording is called while some other thread is inside DoSomething. Since creating a new list from an existing one requires enumerating over it, you are likely to run into the old "Collection was modified; enumeration operation may not execute" problem.
The bottom line: practice safe threading!

It's possible, albeit tricky, to write a linked list that allows simultaneous insertions from multiple threads without a lock, but this isn't it. It's just not safe to call _list.Add in parallel and hope for the best. Depending how it's written, you could lose one or both values, or corrupt the entire structure. Just lock it.

Related

Concurrent acces to a static member in .NET

I've a class that contains a static collection to store the logged-in users in an ASP.NET MVC application. I just want to know about the below code is thread-safe or not. Do I need to lock the code whenever I add or remove item to the onlineUsers collection.
public class OnlineUsers
{
private static List<string> onlineUsers = new List<string>();
public static EventHandler<string> OnUserAdded;
public static EventHandler<string> OnUserRemoved;
private OnlineUsers()
{
}
static OnlineUsers()
{
}
public static int NoOfOnlineUsers
{
get
{
return onlineUsers.Count;
}
}
public static List<string> GetUsers()
{
return onlineUsers;
}
public static void AddUser(string userName)
{
if (!onlineUsers.Contains(userName))
{
onlineUsers.Add(userName);
if (OnUserAdded != null)
OnUserAdded(null, userName);
}
}
public static void RemoveUser(string userName)
{
if (onlineUsers.Contains(userName))
{
onlineUsers.Remove(userName);
if (OnUserRemoved != null)
OnUserRemoved(null, userName);
}
}
}
That is absolutely not thread safe. Any time 2 threads are doing something (very common in a web application), chaos is possible - exceptions, or silent data loss.
Yes you need some kind of synchronization such as lock; and static is usually a very bad idea for data storage, IMO (unless treated very carefully and limited to things like configuration data).
Also - static events are notorious for a good way to keep object graphs alive unexpectedly. Treat those with caution too; if you subscribe once only, fine - but don't subscribe etc per request.
Also - it isn't just locking the operations, since this line:
return onlineUsers;
returns your list, now unprotected. all access to an item must be synchronized. Personally I'd return a copy, i.e.
lock(syncObj) {
return onlineUsers.ToArray();
}
Finally, returning a .Count from such can be confusing - as it is not guaranteed to still be Count at any point. It is informational at that point in time only.
Yes, you need to lock the onlineUsers to make that code threadsafe.
A few notes:
Using a HashSet<string> instead of the List<string> may be a good idea, since it is much more efficient for operations like this (Contains and Remove especially). This does not change anything on the locking requirements though.
You can declare a class as "static" if it has only static members.
Yes you do need to lock your code.
object padlock = new object
public bool Contains(T item)
{
lock (padlock)
{
return items.Contains(item);
}
}
Yes. You need to lock the collection before you read or write to the collection, since multiple users are potentially being added from different threadpool workers. You should probably also do it on the count as well, though if you're not concerned with 100% accuracy that may not be an issue.
As per Lucero's answer, you need to lock onlineUsers. Also be careful what will clients of your class do with the onlineUsers returned from GetUsers(). I suggest you change your interface - for example use IEnumerable<string> GetUsers() and make sure the lock is used in its implementation. Something like this:
public static IEnumerable<string> GetUsers() {
lock (...) {
foreach (var element in onlineUsers)
yield return element;
// We need foreach, just "return onlineUsers" would release the lock too early!
}
}
Note that this implementation can expose you to deadlocks if users try to call some other method of OnlineUsers that uses lock, while still iterating over the result of GetUsers().
That code it is not thread-safe per se.
I will not make any suggestions relative to your "design", since you didn't ask any. I'll assume you found good reasons for those static members and exposing your list's contents as you did.
However, if you want to make your code thread-safe, you should basically use a lock object to lock on, and wrap the contents of your methods with a lock statement:
private readonly object syncObject = new object();
void SomeMethod()
{
lock (this.syncObject)
{
// Work with your list here
}
}
Beware that those events being raised have the potential to hold the lock for an extended period of time, depending on what the delegates do.
You could omit the lock from the NoOfOnlineUsers property while declaring your list as volatile. However, if you want the Count value to persist for as long as you are using it at a certain moment, use a lock there, as well.
As others suggested here, exposing your list directly, even with a lock, will still pose a "threat" on it's contents. I would go with returning a copy (and that should fit most purposes) as Mark Gravell advised.
Now, since you said you are using this in an ASP.NET environment, it is worth saying that all local and member variables, as well as their member variables, if any, are thread safe.

C# Thread Locking Problem

I am creating a solution which has 2 classes
Class A has a public static List object i.e. public static List<MyClass> classes = new List<MyClass>();
Class B has methods which are running using System.Threading.Timer and call methods of class A on timely intervals
Class A has two methods
Method 1: Update the static List - Finds an item and increment its property e.g.
classes[0].Id = i++;
Method 2: Return the static List
But I keep getting exception that List cannot be modified.
I want to ensure that only one method is locking the classes object at one time. What can I do to achieve it? lock(this) or lock(classes) didn't work.
Exception is along the lines that
list cannot be modifed when it is being enumerated.
It points to the line where classes[0].Id is incremented
Code is:
for (int i = 0; i< classes.Count;i++)
{
if (classes[i].Name == this.NameToFind)
{
classes[i].Id = n++;
}
}
Please note that I want to modify classes list object as the updated object is being returned by the other method.
It sounds like class A should expose less of it's internals. You've not said much about the design but would this (or similar work)
class A{
List<MyClass> _list = new List<MyClass>();
object _lock = new object();
public void Increment(int index){
lock(_lock) {/*find item and increment */}
}
}
Ideally there would be no static state, B (your message pump) would have access directly or via an interface to an instance of A. If you really need static then make _list and _lock static (but I don't like that).
As already asked, there needs to be more info on the exception
According to some of the comments on the answers Class A is a Wcf Service and class B is a consuming the service. Those details could have been potentially important as whatever is being returned undergoes serialization.
From what you are describing about the exception, I think we are missing details. You shouldn't be getting that error with out something that uses an enumerator.
As to locking, it sounds like you need a private static object to lock on (since I'm guessing you want to synchronize operations on that static list across instanced wcf calls), but it depends on how you setup your wcf concurrency mode. There are likely more efficient ways to deal with the synchro than the below example, but with what I know it's all I can do. Make sure that anything that touches the private list does so inside the static lock. You probably should look into a reader writer slim lock http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx
(handwritten)
class A
{
private static readonly object listLock = new object();
private static List<MyClass> classes = new List<MyClass>();
public void Method1()
{
lock(listLock)
{
//update here
}
}
public List<MyClass> Method2()
{
lock(listLock)
{
return classes;
}
}
}

C# Add class instance with internal timer to a static List, is it safe?

My program has a static list of type classA. ClassA implements a threading timer that executes a task. The list may contain as many instances of classA as desired. Is this technique causing threading issues where the class instances can block each other? It that is the case how can I solve the that problem. ex:
static List<MyClassType> list=null;
void static Main()
{
list = new List<MyClassType>();
var a = new MyClassType();
var b = new MyClassType();
list.Add(a);
list.Add(b);
Console.ReadKey();
}
a and b will execute theire internal task based on the timer.Is it s bsd technique? Why?
It really depends on what the timer tasks do. Just because there are references to various objects from the same list doesn't affect how their threads are scheduled etc.
It would be unsafe if the timer action started mutating the list - List<T> isn't thread-safe beyond multiple readers. If one of the parts of the timer task needs to remove the instance from the list (for example) then you'll need locking to make that work appropriately - and you'll also need to be careful when iterating over the list, etc.
The code is not thread-safe, if thats what you mean.
If methods like add and remove are called from the threads and they are called at the same time it will cause your list to break.
You can solve this by using lock(list){ list.add(); list.remove(); } every time you use the list.
But that's messy because you might forget... A much better solution is to override the List class and make your own safe implementation of it:
public class ThreadSafeList<T> : List<T>
{
private List<T> list;
// Use any normal List constructor here.
public ThreadSafeList(List<T> list)
{
this.list = list;
}
public bool Add(T item)
{
lock (list)
{
return this.Add(item);
}
}
}
And of course also implement the remaining methods, use lock on the ones that might change anything in the List.

C# Static Property Locking

Just looking for a code review of this code. ASP.net Cache is not an option. The static list will be accessed a lot on a website that gets well over 10K page views per day and concurrent read attempts is likely. On app restart when the list is rebuilt I was wondering if there are any issues I may be overlooking? Is locking on the list being instantiated best practice?
public class MyClass
{
private static List<Entry> _listCache = null;
protected static List<Entry> ListCache
{
get
{
if (_listCache == null)
{
_listCache = new List<Entry>();
lock (_listCache)
{
//Add items to the list _listCache from XML file
}
}
return _listCache;
}
}
//....Other methods that work with the list
}
10k views - that's one every 8 seconds... not sure you need to worry too much... ;-p
But re the code - that is overcomplicating things, and you could still end up initializing it twice. I'd just use a static constructor to do this; it'll be more robust. If you must have full isolated lazy loading (even with other static methods on the type), there is a trick with an inner class to achieve the same:
public class MyClass
{
static class InnerCache {
internal static readonly IList<Entry> _listCache;
static InnerCache() {
List<Entry> tmp = new List<Entry>();
//Add items to the list _listCache from XML file
_listCache = new ReadOnlyCollection<Entry>(tmp);
}
}
protected static IList<Entry> ListCache {
get {return InnerCache._listCache;}
}
}
I would also be concerned about the chance of somebody mutating the list - might want to use a readonly list!
There's not really a reason this wouldn't work for you. However, if you want to do it the way your sample code is, you want to lock before you check to see if _listCache is null. So you would need a separate monitor to lock on. Something like this:
public class MyClass
{
private static object _listCacheMonitor = new object();
private static List<Entry> _listCache = null;
protected static List<Entry> ListCache
{
get
{
lock (_listCacheMonitor) {
if (_listCache == null)
{
_listCache = new List<Entry>();
//Add items to the list _listCache from XML file
}
}
return _listCache;
}
}
//....Other methods that work with the list
}
A static constructor may be your best bet here. A static constructor will block all threads that depend on it while it's running, and it will only run once. As you have the code here, the lock doesn't really do anything, and there are lots of ways that bad things can happen, including multiple Lists being initialized from XML at the same time. In fact, one thread could create a new List then lock and load a different list and then return a third list, depending on when the thread switching occurs.
Multiple threads can initalize _listCache. Depending on the code generation optimizations and runtime execution optimization, this may result in multiple threads locking and updating different objects. And besides, you can't expose the list as a property allowing anyone to adds/remove object w/o a lock.
You'd be better using an immutable list that multiple readers can safely parse in read-only mode. Alternatively you can use a Read-Write lock, but things will get pretty hairy, between the initialization control and the access r-w control.

Properly locking a List<T> in MultiThreaded Scenarios?

Okay, I just can't get my head around multi-threading scenarios properly. Sorry for asking a similar question again, I'm just seeing many different "facts" around the internet.
public static class MyClass {
private static List<string> _myList = new List<string>;
private static bool _record;
public static void StartRecording()
{
_myList.Clear();
_record = true;
}
public static IEnumerable<string> StopRecording()
{
_record = false;
// Return a Read-Only copy of the list data
var result = new List<string>(_myList).AsReadOnly();
_myList.Clear();
return result;
}
public static void DoSomething()
{
if(_record) _myList.Add("Test");
// More, but unrelated actions
}
}
The idea is that if Recording is activated, calls to DoSomething() get recorded in an internal List, and returned when StopRecording() is called.
My specification is this:
StartRecording is not considered Thread-Safe. The user should call this while no other Thread is calling DoSomething(). But if it somehow could be, that would be great.
StopRecording is also not officially thread-safe. Again, it would be great if it could be, but that is not a requirement.
DoSomething has to be thread-safe
The usual way seems to be:
public static void DoSomething()
{
object _lock = new object();
lock(_lock){
if(_record) _myList.Add("Test");
}
// More, but unrelated actions
}
Alternatively, declaring a static variable:
private static object _lock;
public static void DoSomething()
{
lock(_lock){
if(_record) _myList.Add("Test");
}
// More, but unrelated actions
}
However, this answer says that this does not prevent other code from accessing it.
So I wonder
How would I properly lock a list?
Should I create the lock object in my function or as a static class variable?
Can I wrap the functionality of Start and StopRecording in a lock-block as well?
StopRecording() does two things: Set a boolean variable to false (to prevent DoSomething() from adding more stuff) and then copying the list to return a copy of the data to the caller). I assume that _record = false; is atomic and will be in effect immediately? So normally I wouldn't have to worry about Multi-Threading here at all, unless some other Thread calls StartRecording() again?
At the end of the day, I am looking for a way to express "Okay, this list is mine now, all other threads have to wait until I am done with it".
I will lock on the _myList itself here since it is private, but using a separate variable is more common. To improve on a few points:
public static class MyClass
{
private static List<string> _myList = new List<string>;
private static bool _record;
public static void StartRecording()
{
lock(_myList) // lock on the list
{
_myList.Clear();
_record = true;
}
}
public static IEnumerable<string> StopRecording()
{
lock(_myList)
{
_record = false;
// Return a Read-Only copy of the list data
var result = new List<string>(_myList).AsReadOnly();
_myList.Clear();
return result;
}
}
public static void DoSomething()
{
lock(_myList)
{
if(_record) _myList.Add("Test");
}
// More, but unrelated actions
}
}
Note that this code uses lock(_myList) to synchronize access to both _myList and _record. And you need to sync all actions on those two.
And to agree with the other answers here, lock(_myList) does nothing to _myList, it just uses _myList as a token (presumably as key in a HashSet). All methods must play fair by asking permission using the same token. A method on another thread can still use _myList without locking first, but with unpredictable results.
We can use any token so we often create one specially:
private static object _listLock = new object();
And then use lock(_listLock) instead of lock(_myList) everywhere.
This technique would have been advisable if myList had been public, and it would have been absolutely necessary if you had re-created myList instead of calling Clear().
Creating a new lock in DoSomething() would certainly be wrong - it would be pointless, as each call to DoSomething() would use a different lock. You should use the second form, but with an initializer:
private static object _lock = new object();
It's true that locking doesn't stop anything else from accessing your list, but unless you're exposing the list directly, that doesn't matter: nothing else will be accessing the list anyway.
Yes, you can wrap Start/StopRecording in locks in the same way.
Yes, setting a Boolean variable is atomic, but that doesn't make it thread-safe. If you only access the variable within the same lock, you're fine in terms of both atomicity and volatility though. Otherwise you might see "stale" values - e.g. you set the value to true in one thread, and another thread could use a cached value when reading it.
There are a few ways to lock the list. You can lock on _myList directly providing _myList is never changed to reference a new list.
lock (_myList)
{
// do something with the list...
}
You can create a locking object specifically for this purpose.
private static object _syncLock = new object();
lock (_syncLock)
{
// do something with the list...
}
If the static collection implements the System.Collections.ICollection interface (List(T) does), you can also synchronize using the SyncRoot property.
lock (((ICollection)_myList).SyncRoot)
{
// do something with the list...
}
The main point to understand is that you want one and only one object to use as your locking sentinal, which is why creating the locking sentinal inside the DoSomething() function won't work. As Jon said, each thread that calls DoSomething() will get its own object, so the lock on that object will succeed every time and grant immediate access to the list. By making the locking object static (via the list itself, a dedicated locking object, or the ICollection.SyncRoot property), it becomes shared across all threads and can effectively serialize access to your list.
The first way is wrong, as each caller will lock on a different object.
You could just lock on the list.
lock(_myList)
{
_myList.Add(...)
}
You may be misinterpreting the this answer, what is actually being stated is that they lock statement is not actually locking the object in question from being modified, rather it is preventing any other code using that object as a locking source from executing.
What this really means is that when you use the same instance as the locking object the code inside the lock block should not get executed.
In essence you are not really attempting to "lock" your list, you are attempting to have a common instance that can be used as a reference point for when you want to modify your list, when this is in use or "locked" you want to prevent other code from executing that would potentially modify the list.

Categories

Resources