Proper locking in thread-safe self-generating list (C#) - c#

I have a singleton IEnumerable that generates a sequence of numbers. The sequence is interable (basically indefinitely) and I generate the next number in the sequence only when needed.
public class Generator:IEnumerable<long> {
private Generator() { }
private static volatile Generator instance=new Generator();
private static readonly object syncRoot=new object();
public static Generator Instance { get { return instance; } }
private static List<long> numsList=new List<long>();
private void GenerateNextNumber() {
long number;
//Code to generate next number
numsList.Add(number);
}
private long GenerateToNthNumber(int n) {
lock(syncRoot) {
while(numsList.Count<n)
GenerateNextNumber();
}
return numsList[n-1];
}
public static long GetNthNumber(int n) {
return Instance.GenerateToNthNumber(n);
}
private class GeneratorEnumerator:IEnumerator<long> {
private int index=0;
public long Current { get { return GetNthNumber(index); } }
public void Dispose() { }
object System.Collections.IEnumerator.Current { get { return GetNthNumber(index); } }
public bool MoveNext() {
index++;
return true;
}
public void Reset() {
index=0;
}
}
public IEnumerator<long> GetEnumerator() {
return new GeneratorEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
This code works enumerating through and summing the numbers in concurrent threads. Is there a way to prevent having to lock every time GenerateToNthNumber is called? I tried this code:
private long GenerateToNthNumber(int n) {
if(numsList.Count<n) {
lock(syncRoot) {
while(numsList.Count<n)
GenerateNextNumber();
}
}
return numsList[n-1];
}
But when testing enumerating through and summing the numbers in multiple concurrent threads, not all the results end up with the same sum. My objective is to have non-blocking reads if the number being asked for is already generated, if that is even possible. Is there a better way to do this?

The way List is implemented, it cannot be safely read in one thread while it is being written in another. I would suggest that instead you use nested known-size arrays which, once allocated, are never abandoned (e.g. once an array is allocated that will hold theList[15691], the item will never be held by any other array). Such things may easily be used to implement an add-only list which requires locking when adding items, but is inherently thread-safe for reading without locking.

Have you thought about using a thread safe collection?
http://msdn.microsoft.com/en-us/library/dd997305.aspx

Related

I can't use a foreach loop twice in my code, why?

I am currently trying to learn C# and I am giving it a shot to implement Queue from scratch.
Currently I am trying to implement foreach functionality so I can print out my queue.
I have an issue when I use a foreach loop twice in my code it wont print anything the second time I use it. I have managed to see that my Current method in the Queue class isn't being used the second time I use the foreach loop (with help of the print statement of the int position variable, which doesnt print out anything the second time a foreach is being used).
I appreciate any help to understand why I can't use a foreach loop twice in my code. And if there is anything else which can be improved with my code, that would be greatly appreciated as well.
The RunTest class below is where I test my implementation of my Queue class.
namespace RunTest
{
class RunTest
{
public static void Main(string[] args){
Queue<string> queueOfStrings = new Queue<string>();
queueOfStrings.Enqueue("Dog");
queueOfStrings.Enqueue("Cat");
queueOfStrings.Enqueue("Mouse");
queueOfStrings.Enqueue("Bird");
System.Console.WriteLine("Foreach: \n");
foreach(string item in queueOfStrings){
System.Console.WriteLine(item);
}
System.Console.WriteLine("\n");
System.Console.WriteLine("Peek: "+queueOfStrings.Peek());
System.Console.WriteLine("Dequeue : "+queueOfStrings.Dequeue());
System.Console.WriteLine("Peek: "+queueOfStrings.Peek());
System.Console.WriteLine("Foreach: ");
foreach(string item2 in queueOfStrings){
System.Console.WriteLine(item2);
}
}
}
}
And here is my Queue class:
using System;
using System.Collections;
using System.Collections.Generic;
public class Queue<T> : IEnumerator,IEnumerable{
private LinkedList<T> list = new LinkedList<T>();
private T[] storeElements;
private int position = -1;
public Queue()
{
Console.WriteLine("Queue initialized \n");
}
public void Enqueue(T data){
list.AddFirst(data);
}
public int Count(){
return list.Count;
}
public void Clear(){
list.Clear();
}
public T Dequeue(){
T data = list.Last.Value;
list.RemoveLast();
return data;
}
public T Peek(){
return list.Last.Value;
}
private void ToArray(){
storeElements = new T[Count()];
list.CopyTo(storeElements, 0);
Array.Reverse(storeElements);
}
//IEnumerator and IEnumerable require these methods.
public IEnumerator GetEnumerator()
{
ToArray();
return (IEnumerator)this;
}
//IEnumerator
public bool MoveNext()
{
position++;
return (position < Count());
}
//IEnumerable
public void Reset()
{
position = 0;
}
//IEnumerable
public object Current
{
get { System.Console.WriteLine(position); return storeElements[position];}
}
}
Using the queue itself as the enumerator isn't a great idea-- it will really limit how the class can be used. Imagine for example if you wanted to check the queue for duplicates-- you'd have to create a nested loop, which means two simultaneous enumerators. It simply wouldn't work because there is only one position variable.
Take a look at how built-in classes do it. They return a new instance of a separate enumerator class (e.g. an array will create a SZArrayEnumerator). In your case, you can probably leverage the enumerator provided by the backing field itself, like this:
public IEnumerator GetEnumerator()
{
ToArray();
return storeElements.GetEnumerator();
}

What collection to use for a rotating list of last actions?

I'm looking for a C# collection type that allow me to define a maximum capacity. I would like to add objects to this collection and when my capacity is reached the oldest object should be replaced by the new one.
Specifically, I would like to create a collection that memorizes my last 10 or 20 actions.
I already read articles on Google but I'm looking for answers from this community.
The only fixed collection type in .NET is an array, so that is the only one meeting your requirement.
You can keep an index to do the rotating. You just have to remember what your next location to write to is.
Something like this:
int index = 0;
string[] collection = new string[10];
public void Write(string text)
{
index %= collection.Length; // prevent overflowing
collection[index++] = text;
}
If your application is not performance-sensitive, then you can use a generic collection Queue.
Here is the example wrapper which can solve your problem:
public class LimitedQueue<T>
{
private readonly Queue<T> _queue;
private readonly int _limit;
public LimitedQueue(int limit)
{
_queue = new Queue<T>();
_limit = limit;
}
public void Enqueue(T item)
{
if (_queue.Count == _limit) _queue.Dequeue();
_queue.Enqueue(item);
}
public T Dequeue()
{
return _queue.Dequeue();
}
public T Peek()
{
return _queue.Peek();
}
public T[] GetAll()
{
return _queue.ToArray();
}
}
It is less performant than an array but it lets you do something useful things like getting all items from the Queue.
The type you are describing I've always referred to as a FixedQueue or a fixed size FIFO. The idea is the first in first out but you discard the first out if the size is exceeded:
public class FixedQueue<T>
{
private readonly ConcurrentQueue<T> _innerQueue;
private int _length;
public FixedQueue(int length)
{
_length = length;
_innerQueue = new ConcurrentQueue<T>(length);
}
public void Enqueue(T obj)
{
lock (_innerQueue)
{
if (_innerQueue.Length == _length)
_innerQueue.Dequeue();
_innerQueue.Enqueue(obj);
}
}
public T Dequeue()
{
lock (_innerQueue)
{
return _innerQueue.Dequeue();
}
}
// etc...
}
If you are looking for a more oriented object solution with inheritance and you don't care about maintenance you can write this:
public class FixedQueue<T> : Queue<T>
{
//private readonly ConcurrentQueue<T> _innerQueue;
private int _capacity;
public FixedQueue(int capacity) : base()
{
_capacity = capacity;
}
public void Enqueue(T obj)
{
lock(this)
{
if (this.Count == _capacity)
base.Dequeue();
base.Enqueue(obj);
}
}
public T Dequeue()
{
lock (this)
{
return this.Dequeue();
}
}
}
this solution doesn't respect the new trend that says you should prefer composition over inheritance.

What is a best practice for making a class's properties thread safe?

[Edit: It looks like the original question involved a double and not an integer. So I think this question stands if we change the integer to a double.]
I have rare issue with reading integer properties from a class used in multiple threads that sometimes returns a zero value. The values are not changed after initialization.
This question addresses that. The consensus is that even though I'm accessing an integer I need to synchronize the properties. (Some of the original answers have been deleted). I haven't chosen an answer there because I have not resolved my issue yet.
So I’ve done some research on this and I’m not sure which of .Net 4’s locking mechanisms to use or if the locks should be outside the class itself.
This is what I thought about using:
public class ConfigInfo
{
private readonly object TimerIntervalLocker = new object();
private int _TimerInterval;
public int TimerInterval
{
get
{
lock (TimerIntervalLocker) {
return _TimerInterval;
}
}
}
private int _Factor1;
public int Factor1
{
set
{
lock (TimerIntervalLocker) {
_Factor1 = value;
_TimerInterval = _Factor1 * _Factor2;
}
}
get
{
lock (TimerIntervalLocker) {
return _Factor1;
}
}
}
private int _Factor2;
public int Factor2
{
set
{
lock (TimerIntervalLocker) {
_Factor2 = value;
_TimerInterval = _Factor1 * _Factor2;
}
}
get
{
lock (TimerIntervalLocker) {
return _Factor2;
}
}
}
}
But I’ve read that this is horribly slow.
Another alternative is to lock the instance of ConfigData on the user side but that seems to be a lot of work. Another alternative I’ve seen is Monitor.Enter and Monitor.Exit but I think Lock is the same thing with less syntax.
So what is a best practice for making a class's properties thread
safe?
a. Using lock can be slow since it uses operating system resources, if the properties' complexity is low, then spin lock (or interlocked.compareexchange) will be faster.
b. You have to make sure that a thread won't enter a lock and via a call from one property to another get locked out. - If this can happen (non currently an issue in your code), you'll need to make the lock thread or task sensitive.
Edit:
If the object is supposed to be set during initialization and never changed, make it immutable (like .NET strings are). Remove all the public setters and provide a constructor with parameters for defining the initial state and perhaps additional methods/operators for creating a new instance with a modified state (e.g. var newString = "Old string" + " was modified.";).
If the values never change, it would be easier to just make a copy of that instance and pass each thread an instance of it's own. No locking required at all.
I think you should rewrite your ConfigInfo class to look like this; then you can't get overflow or threading problems:
public sealed class ConfigInfo
{
public ConfigInfo(int factor1, int factor2)
{
if (factor1 <= 0)
throw new ArgumentOutOfRangeException("factor1");
if (factor2 <= 0)
throw new ArgumentOutOfRangeException("factor2");
_factor1 = factor1;
_factor2 = factor2;
checked
{
_timerInterval = _factor1*_factor2;
}
}
public int TimerInterval
{
get
{
return _timerInterval;
}
}
public int Factor1
{
get
{
return _factor1;
}
}
public int Factor2
{
get
{
return _factor2;
}
}
private readonly int _factor1;
private readonly int _factor2;
private readonly int _timerInterval;
}
Note that I'm using checked to detect overflow problems.
Otherwise some values will give incorrect results.
For example, 57344 * 524288 will give zero in unchecked integer arithmetic (and there's very many other pairs of values that will give zero, and even more that will give a negative result or a positive value that "seems" correct).
It is best, as mentioned in the comments, to make the properties readonly. I thought about the following possibility:
public class ConfigInfo
{
private class IntervalHolder
{
public static readonly IntervalHolder Empty = new IntervalHolder();
private readonly int _factor1;
private readonly int _factor2;
private readonly int _interval;
private IntervalHolder()
{
}
private IntervalHolder(int factor1, int factor2)
{
_factor1 = factor1;
_factor2 = factor2;
_interval = _factor1*_factor2;
}
public IntervalHolder WithFactor1(int factor1)
{
return new IntervalHolder(factor1, _factor2);
}
public IntervalHolder WithFactor2(int factor2)
{
return new IntervalHolder(_factor1, factor2);
}
public int Factor1
{
get { return _factor1; }
}
public int Factor2
{
get { return _factor2; }
}
public int Interval
{
get { return _interval; }
}
public override bool Equals(object obj)
{
var otherHolder = obj as IntervalHolder;
return
otherHolder != null &&
otherHolder._factor1 == _factor1 &&
otherHolder._factor2 == _factor2;
}
}
private IntervalHolder _intervalHolder = IntervalHolder.Empty;
public int TimerInterval
{
get { return _intervalHolder.Interval; }
}
private void UpdateHolder(Func<IntervalHolder, IntervalHolder> update)
{
IntervalHolder oldValue, newValue;
do
{
oldValue = _intervalHolder;
newValue = update(oldValue);
} while (!oldValue.Equals(Interlocked.CompareExchange(ref _intervalHolder, newValue, oldValue)));
}
public int Factor1
{
set { UpdateHolder(holder => holder.WithFactor1(value)); }
get { return _intervalHolder.Factor1; }
}
public int Factor2
{
set { UpdateHolder(holder => holder.WithFactor2(value)); }
get { return _intervalHolder.Factor2; }
}
}
This way, your TimerInterval value is always in sync with its factors. The only problem is when some thread reads one of the properties while another writes them from outside the ConfigInfo. The first one could get wrong value and I don't see any way to solve this without introducing a single lock root. The question is whether read operations are critical.

How to Create a Thread-Safe Generic List?

I have a Generic List as below
public static readonly List<Customer> Customers = new List<Customer>();
I'm using the below methods for it:
.Add
.Find
.FirstOrDefault
The last 2 are LINQ extensions.
I'd need to make this thread-safe to be able to run multiple instances of the container class.
How to achieve that?
If those are the only functions you are using on List<T> then the easiest way is to write a quick wrapper that synchronizes access with a lock
class MyList<T> {
private List<T> _list = new List<T>();
private object _sync = new object();
public void Add(T value) {
lock (_sync) {
_list.Add(value);
}
}
public bool Find(Predicate<T> predicate) {
lock (_sync) {
return _list.Find(predicate);
}
}
public T FirstOrDefault() {
lock (_sync) {
return _list.FirstOrDefault();
}
}
}
I highly recommend the approach of a new type + private lock object. It makes it much more obvious to the next guy who inherits your code what the actual intent was.
Also note that .Net 4.0 introduced a new set of collections specifically aimed at being used from multiple threads. If one of these meets your needs I'd highly recommend using it over rolling your own.
ConcurrentStack<T>
ConcurrentQueue<T>
To expand on #JaradPar's answer, here is a full implementation with a few extra features, as described in the summary
/// <summary>
/// a thread-safe list with support for:
/// 1) negative indexes (read from end). "myList[-1]" gets the last value
/// 2) modification while enumerating: enumerates a copy of the collection.
/// </summary>
/// <typeparam name="TValue"></typeparam>
public class ConcurrentList<TValue> : IList<TValue>
{
private object _lock = new object();
private List<TValue> _storage = new List<TValue>();
/// <summary>
/// support for negative indexes (read from end). "myList[-1]" gets the last value
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public TValue this[int index]
{
get
{
lock (_lock)
{
if (index < 0)
{
index = this.Count - index;
}
return _storage[index];
}
}
set
{
lock (_lock)
{
if (index < 0)
{
index = this.Count - index;
}
_storage[index] = value;
}
}
}
public void Sort()
{
lock (_lock)
{
_storage.Sort();
}
}
public int Count
{
get
{
lock (_lock) return _storage.Count;
}
}
bool ICollection<TValue>.IsReadOnly
{
get
{
return ((IList<TValue>)_storage).IsReadOnly;
}
}
public void Add(TValue item)
{
lock (_lock)
{
_storage.Add(item);
}
}
public void Clear()
{
lock (_lock)
{
_storage.Clear();
}
}
public bool Contains(TValue item)
{
lock (_lock)
{
return _storage.Contains(item);
}
}
public void CopyTo(TValue[] array, int arrayIndex)
{
lock (_lock)
{
_storage.CopyTo(array, arrayIndex);
}
}
public int IndexOf(TValue item)
{
lock (_lock)
{
return _storage.IndexOf(item);
}
}
public void Insert(int index, TValue item)
{
lock (_lock)
{
_storage.Insert(index, item);
}
}
public bool Remove(TValue item)
{
lock (_lock)
{
return _storage.Remove(item);
}
}
public void RemoveAt(int index)
{
lock (_lock)
{
_storage.RemoveAt(index);
}
}
public IEnumerator<TValue> GetEnumerator()
{
lock (_lock)
{
return _storage.ToArray().AsEnumerable().GetEnumerator();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
If you're using version 4 or greater of the .NET framework you can use the thread-safe collections.
You can replace List<T> with ConcurrentBag<T>:
namespace Playground.Sandbox
{
using System.Collections.Concurrent;
using System.Threading.Tasks;
public static class Program
{
public static void Main()
{
var items = new[] { "Foo", "Bar", "Baz" };
var bag = new ConcurrentBag<string>();
Parallel.ForEach(items, bag.Add);
}
}
}
You will need to use locks in every place where the collection gets modified or iterated over.
Either that or use one of the new thread-safe data structures, like ConcurrentBag.
Use the lock keyword when you manipulate the collection, ie: your Add/Find:
lock(Customers) {
Customers.Add(new Customer());
}
Never use ConcurrangBag for ordered data. Use Array instead
Make your Action as accessible by one only by using lock on any private object
Refer to : Thread Safe Generic Queue Class
http://www.codeproject.com/Articles/38908/Thread-Safe-Generic-Queue-Class
Ok, so I had to completely rewrite my answer. After 2 days of testing I have to say that the JasonS's code has some defects, I guess because of Enumerators. While one thread uses foreach, and the other other changes the list, it throws exceptions.
So I found this answer, and it works for me fine the last 48 hours non-stop, I guess more than 100k threads were created in my application, and used that lists.
The only thing I changed - I've moved entering the locks outside the try-finally section. Read here about the possible exceptions. Also, if you will read MSDN, they have the same approach.
But, as were mentioned in link below, List can not be 100% thread safe, probably that is why there is no default ConcurentList implementation in c#.

Using a List from 2 different threads?

I have a list where it is entries can be updated, new data inserted or removed from 2 different threads.
Is it ok to use a public readonly object to lock when it is being used to interact to the other thread as to when it is locked or not or what would be the correct way to use this list across the 2 threads ?
You should always use a lock when accessing the list on different threads.
public class Sample
{
object synch = new object();
List<Something> list = new List<Something>();
void Add(Something something)
{
lock (synch) { list.Add(something); }
}
// Add the methods for update and delete.
}
You should wrap this in a class that handles the locking for you, or use a thread-safe collection, such as ConcurrentQueue<T> or one of the other collections in System.Collections.Concurrent.
Exposing the synchronization object to a public API is dangerous, and not a good practice.
First, read this article to understand why it's bad: http://blogs.msdn.com/b/jaredpar/archive/2009/02/11/why-are-thread-safe-collections-so-hard.aspx
Then, do it anyway like I did:
public abstract class ConcurrentCollection<T> : ICollection<T>
{
private List<T> List { get; set; }
public ConcurrentCollection()
{
this.List = new List<T>();
}
public T this[int index]
{
get
{
return this.List[index];
}
}
protected virtual void AddUnsafe(T item)
{
this.List.Add(item);
}
protected virtual void RemoveUnsafe(T item)
{
this.List.Remove(item);
}
protected virtual void ClearUnsafe()
{
this.List.Clear();
}
public void Add(T item)
{
lock (this.List)
{
this.AddUnsafe(item);
}
}
public bool Remove(T item)
{
lock (this.List)
{
this.RemoveUnsafe(item);
return true;
}
}
public void Clear()
{
lock (this.List)
{
this.ClearUnsafe();
}
}
public int Count
{
get
{
lock (this.List)
{
return this.List.Count;
}
}
}
public bool IsReadOnly
{
get
{
return false;
}
}
public bool Contains(T item)
{
lock (this.List)
{
return this.List.Contains(item);
}
}
public void CopyTo(T[] array, int arrayIndex)
{
lock (this.List)
{
this.List.CopyTo(array, arrayIndex);
}
}
public IEnumerator<T> GetEnumerator()
{
return new ConcurrentEnumerator<T>(this.List, this.List);
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException("Abstract concurrent enumerators not implemented.");
}
}
public class ConcurrentEnumerator<T> : IEnumerator<T>
{
private int Position = -1;
private List<T> Duplicate;
private object Mutex;
private ICollection<T> NonConcurrentCollection;
internal ConcurrentEnumerator(ICollection<T> nonConcurrentCollection, object mutex)
{
this.NonConcurrentCollection = nonConcurrentCollection;
this.Mutex = mutex;
lock (this.Mutex)
{
this.Duplicate = new List<T>(this.NonConcurrentCollection);
}
}
public T Current
{
get
{
return this.Duplicate[this.Position];
}
}
object IEnumerator.Current
{
get
{
return this.Current;
}
}
public bool MoveNext()
{
this.Position++;
lock (this.Mutex)
{
while (this.Position < this.Duplicate.Count && !this.NonConcurrentCollection.Contains(this.Current))
{
this.Position++;
}
}
return this.Position < this.Duplicate.Count;
}
public void Reset()
{
this.Position = -1;
}
public void Dispose() { }
}
// Standards have List as derived Collection...
public class ConcurrentList<T> : ConcurrentCollection<T> { }
This code is still not fully safe, for instance the Count example may still crash, but it allows for iteration, adding and removing across threads. If you want to expose the mutex, do so, then lock around it for your other code constructs like count and contains.
But it's still a bad idea.
Edit: Example usage.
ConcurrentList<string> list = new ConcurrentList<string>();
list.Add("hello");
list.Add("world");
list.Add("foo");
list.Add("bar");
foreach (string word in list)
{
if (word == "world")
{
list.Remove("bar"); // Will not crash the foreach!
}
Console.WriteLine(word);
}
Output:
hello
world
foo

Categories

Resources