Reputation: 7334
I came across this puzzle in a programming contest where I am not supposed to use any inbuilt concurrent .NET 4.0 data structures.
I have to override the ToString()
method and this method should support concurrent readers.
This is the solution which I came up with but I strongly believe it is does not support concurrent readers. How can I support concurrent readers without locking the list?
class Puzzle
{
private List<string> listOfStrings = new List<string>();
public void Add(string item)
{
lock (listOfStrings)
{
if (item != null)
{
listOfStrings.Add(item);
}
}
}
public override string ToString()
{
lock (listOfStrings)
{
return string.Join(",", listOfStrings);
}
}
}
Upvotes: 2
Views: 783
Reputation: 185663
Because List<T>
is just a T[]
under the hood, there's nothing unsafe about reading the list from multiple threads. Your issue is that reading while writing and writing concurrently are unsafe. Because of this, you should use ReaderWriterLockSlim.
class Puzzle
{
private List<string> listOfStrings = new List<string>();
private ReaderWriterLockSlim listLock = new ReaderWriterLockSlim();
public void Add(string item)
{
listLock.EnterWriteLock();
try
{
listOfStrings.Add(item);
}
finally
{
listlock.ExitWriteLock();
}
}
public override string ToString()
{
listLock.EnterReadLock();
try
{
return string.Join(",", listOfStrings);
}
finally
{
listLock.ExitReadLock();
}
}
}
ReaderWriterLockSlim
will allow multiple threads to enter the lock in read mode, but they will all block if/while something is in the lock in write mode. Likewise, entering the lock in write mode will block until all threads have exited the lock in read mode. The practical outworking is that multiple reads can happen at the same time as long as nothing is writing, and one write operation can happen at a time as long as nothing is reading.
Upvotes: 8
Reputation: 18895
Since it doesn't look like Remove isn't a requirement, why can't you just return a string?
class Puzzle
{
private string Value { get; set; }
public Puzzle()
{
Value = String.Empty;
}
public void Add(String item)
{
Value += "," + item;
}
public override string ToString()
{
return Value;
}
}
Upvotes: 0