I need to keep track of a sequential Id, this is being returned to me via a SP which is doing a max(id) across 4 tables, there is no identifer/sequence in the db which is managing the sequence. This will obviously have concurrency issues so i created a helper class to ensure unique Id's are always generated.
The helper is initialised via its repository, which initially calls the DB to find the current Id, all subsequent requests for an Id are serviced in memory via the helper. There will only ever be 1 app using the DB (mine) so i dont need to worry about someone else coming along and creating transactions & throwing the Id out of sync. I think ive got the basics of thread-saftey but im worried about a race condition when the helper is initialised, can someone please advise :)
private class TransactionIdProvider
{
private static readonly object Accesslock = new object();
private int _transactionId;
public int NextId
{
get
{
lock (Accesslock)
{
if(!Initialised) throw new Exception("Must Initialise with id first!!");
return _transactionId++;
}
}
}
public bool Initialised { get; private set; }
public void SetId(int id)
{
lock (Accesslock)
{
if (Initialised) return;
_transactionId = id;
Initialised = true;
}
}
public TransactionIdProvider()
{
Initialised = false;
}
}
The helper class is initialised in a repository:
private static readonly TransactionIdProvider IdProvider = new TransactionIdProvider();
public int GetNextTransactionId()
{
if(!IdProvider.Initialised)
{
// Ask the DB
int? id = _context.GetNextTransactionId().First();
if (!id.HasValue)
throw new Exception("No transaction Id returned");
IdProvider.SetId(id.Value);
}
return IdProvider.NextId;
}
It is thread-safe, but it's unnecessarily slow.
You don't need a lock to just increment a number; instead, you can use atomic math.
Also, you're sharing the lock across all instances (it's static), which is unnecessary. (There's nothing wrong with having two different instances run at once)
Finally, (IMHO) there is no point in having a separate uninitialized state.
I would write it like this:
class TransactionIdProvider {
private int nextId;
public TransactionIdProvider(int id) {
nextId = value;
}
public int GetId() {
return Interlocked.Increment(ref nextId);
}
}
Yes it is thread-safe; however, IMO the lock is too global - a static lock to protect instance data smacks a bit of overkill.
Also, NextId as a property is bad - it changes state, so should be a method.
You might also prefer Interlocked.Increment over a lock, although that changes most of the class.
Finally, in the SetId - if it is already initialised I would throw an exception (InvalidOperationException) rather than blindly ignore the call - that sounds like an error. Of course, that then introduces a tricky interval between checking Initialized and calling SetId - you could just hAve SetId return true if it made the change, and false if it turned out to be initialized at the point of set, but SLaks' approach is nicer.
I don't think this is a good idea, you should find another way to deal with this.
Usually when really unique ids are required and there is no a way computationally valid to check if the id is used, i would use a GUID.
However you can just use interlocked operations instead of locking, you can do it without locking at all.
Look for Interlocked.Increment, Interlocked.Exchange and Interlocked.CompareExchange
private class TransactionIdProvider
{
private volatile int _initialized;
private int _transactionId;
public int NextId
{
get
{
for (;;)
{
switch (_initialized)
{
case 0: throw new Exception("Not initialized");
case 1: return Interlocked.Increment(ref _transactionId);
default: Thread.Yield();
}
}
}
}
public void SetId(int id)
{
if (Interlocked.CompareExchange(ref _initialized, -1, 0) == 0)
{
Interlocked.Exchange(ref _transactionId, id);
Interlocked.Exchange(ref _initialized, 1);
}
}
}
This will give you a warning, but it is normal and is also reported in C# documentation as legal. So ignore that warning with a nice pragma:
// Disable warning "A reference to a volatile field will not be treated as volatile"
#pragma warning disable 0420
If you don't need to check for IsInitialized you can do it in the simplest possible way:
public int NextId()
{
return Interlocked.Increment(ref _transactionId);
}
public void Set(int value)
{
Interlocked.Exchange(ref _transactionId, value);
}
Related
In my project I'm using some static variables which I use for storing values during the running lifetime of the application. Now, 99% of the time I'm only reading these values but from time to time I also need to update them and this will happen from different threads.
When thinking about what might happen with two different threads trying to access the same property e.g. concurrent read/write, I started to conclude that some form of synchronization would needed in order to avoid unexpected values being returned between different process or some risk of race conditions.
In essence I needed to derive a single source of truth. I realize that some properties are atomic like booleans, but my methodology mostly applies for the purpose of strings.
One of the challenges is that these static variables are referenced in many places and between different classes, so I also had to figure out an efficient way to solve this challenge without lots of code re-write.
I've decided to use concurrent dictionaries:
public static readonly ConcurrentDictionary<string, string> AppRunTimeStringDictionary = new();
public static readonly ConcurrentDictionary<string, int> AppRunTimeIntegerDictionary = new();
public static readonly ConcurrentDictionary<string, bool> AppRunTimeBooleanDictionary = new();
In my program.cs file, during the earliest stages of startup I simply add all of the properties needed for the running app:
DeviceProvisioning.AppRunTimeBooleanDictionary.TryAdd("UseGpsReceiver", false);
DeviceProvisioning.AppRunTimeStringDictionary.TryAdd("Latitude", String.Empty);
DeviceProvisioning.AppRunTimeStringDictionary.TryAdd("Longitude", String.Empty);
Then in one of my classes I hard code these properties:
public static bool? UseGpsReceiver
{
get
{
if (AppRunTimeBooleanDictionary.TryGetValue("UseGpsReceiver", out var returnedValue))
return returnedValue;
return null;
}
}
public static string? Latitude
{
get
{
if (AppRunTimeStringDictionary.TryGetValue("Latitude", out var returnedValue))
return returnedValue;
return null;
}
}
public static string? Longitude
{
get
{
if (AppRunTimeStringDictionary.TryGetValue("Longitude", out var returnedValue))
return returnedValue;
return null;
}
}
Now for updating these properties, which happens rarely but will be done every now and then, I'm updating these in just one location i.e. using a single method. This way I can use this common method and simply add more prperties to the switch case over time.
public static void SetRunTimeSettings(string property, object value)
{
switch (property)
{
case "UseGpsReceiver":
// code block
if (AppRunTimeBooleanDictionary.TryGetValue("UseGpsReceiver", out var useGpsReceiver))
{ AppRunTimeBooleanDictionary.TryUpdate("UseGpsReceiver", (bool)value, useGpsReceiver); }
break;
case "Latitude":
// code block
if (AppRunTimeStringDictionary.TryGetValue("Latitude", out var latitude))
{ AppRunTimeStringDictionary.TryUpdate("Latitude", (string)value, latitude); }
break;
case "Longitude":
// code block
if (AppRunTimeStringDictionary.TryGetValue("Latitude", out var longitude))
{ AppRunTimeStringDictionary.TryUpdate("Latitude", (string)value, longitude); }
break;
}
}
If I want to update a property then I simply invoke the method as such:
MyClassName.SetRunTimeSettings("UseGpsReceiver", true);
MyClassName.SetRunTimeSettings("Latitude", "51.1234");
MyClassName.SetRunTimeSettings("Longitude", "51.5678");
Because the properties themselves are public static then I can use the getter from anywhere in the app.
From my initial testing, everything seems to work.
Perceived advantages in this approach:
Using a separate dictionary for each type of property collection i.e. strings/integers etc, means I can simply add more properties to the dictionary any time in the future without the need for referencing a model class in the dictionary, as opposed to the dictionary below:
public static readonly ConcurrentDictionary<string, myModelClass> AppRunTimeStringDictionary = new();
Use of the concurrent dictionary (my understanding) is that any process trying to read the property value from the dictionary will always get the latest value, if a property is being updated then I have less risk in reading an old value. Not such an issue for structured logging but if I was storing keys/secrets/connection strings or anything else, reading an old value might stop some process from being able to function correctly.
Using the concurrent dictionary means I don't have to hand craft my own locking mechanisms, which many people seem not to like doing.
Dictionary applies its own internal locks on the individual objects, so any property not being updated can still be read by other processes without much delay.
If the public static getter ever returned a null value, my thoughts are it would be better to return a null value rather than returning the wrong value. I could always implement some kind of polly or retry mechanism somewhere from the calling process, some short delay before trying to retrieve the property value again (by which time it should have been updated from the other thread that was currently updating it)
Appreciate there will be other ways to approach this, so really what I'm asking here is whether anyone sees any issue in my approach?
I'm not planning to add that many properties to each dictionary, I just want a way to ensure that reads and writes are happening with some form of synchronization and order.
Your SetRunTimeSettings is awful. It relies on methods that follow the Try* pattern, but it itself does not. Also doing a TryGetValue just to then be able to call TryUpdate is just throwing away all of the value of Try* operators anyway. It's a hack.
And you have a clear bug in the code for the "Longitude" case - you're updating "Latitude" inside.
I'd suggest going old school and just do this:
private static bool? _UseGpsReceiver;
private readonly static object _UseGpsReceiverLock = new();
public static bool? UseGpsReceiver
{
get { lock (_UseGpsReceiverLock) return _UseGpsReceiver; }
set { lock (_UseGpsReceiverLock) _UseGpsReceiver = value; }
}
private static string? _Latitude;
private readonly static object _LatitudeLock = new();
public static string? Latitude
{
get { lock (_LatitudeLock) return _Latitude; }
set { lock (_LatitudeLock) _Latitude = value; }
}
private static string? _Longitude;
private readonly static object _LongitudeLock = new();
public static string? Longitude
{
get { lock (_LongitudeLock) return _Longitude; }
set { lock (_LongitudeLock) _Longitude = value; }
}
If you don't want to repeat all of the locks then maybe a Locked<T> class might be of use:
public struct Locked<T>
{
public Locked(T value)
{
_value = value;
}
private T _value;
private readonly object _gate = new();
public T Value
{
get { lock (_gate) return _value; }
set { lock (_gate) _value = value; }
}
}
Then you can write this:
private static Locked<bool?> _UseGpsReceiver;
public static bool? UseGpsReceiver
{
get { return _UseGpsReceiver.Value; }
set { _UseGpsReceiver.Value = value; }
}
private static Locked<string?> _Latitude;
public static string? Latitude
{
get { return _Latitude.Value; }
set { _Latitude.Value = value; }
}
private static Locked<string?> _Longitude;
public static string? Longitude
{
get { return _Longitude.Value; }
set { _Longitude.Value = value; }
}
If you are only setting a single string / int / bool at a time, then you don't need to any thread safety. If you are assigning any single value smaller than a machine word, any reading thread will either see the before value or the after value.
However it looks like you intend to set three values at the same time;
MyClassName.SetRunTimeSettings("UseGpsReceiver", true);
MyClassName.SetRunTimeSettings("Latitude", "51.1234");
MyClassName.SetRunTimeSettings("Longitude", "51.5678");
And I assume you want any reader to see either the old values or the new values. In this case you would need some thread synchronisation around every read / write. Which your current code doesn't have.
You could instead store the three values in a class, then update the reference to that instance in one write operation.
public class GpsSettings{
public bool UseGpsReceiver { get; init; }
public double Latitude { get; init; }
public double Longitude { get; init; }
public static GpsSettings Current;
}
...
// write
GpsSettings.Current = new GpsSettings {
UseGpsReceiver = true,
Latitude = 51.1234,
Longitude = 51.5678
};
// read
var gps = GpsSettings.Current;
var location = $"{gps.Latitude}, {gps.Longitude}";
// but never do this;
var location = $"{GpsSettings.Current.Latitude}, {GpsSettings.Current.Longitude}";
Not everyone would agree with me on this one but my personal approach would be to have a single dictionary of the following type:
Dictionary<string, object>
Wrapped in a separate class with the following methods such as AddValue, GetValue, HasKey, HasValue, and UpdateValue with lock statements. Also notice that you'll have to use somewhat generic methods in order to be able to retrieve the value with the actual type and a default value. For example:
public static T GetValue<T>(string key, T defaultValue)
Also, I don't see a problem with your approach but if you want to synchronize things then you'll need n dedicated locks for n dictionaries which I don't think is a clean way; unless I'm missing something, and of course registering multiple dictionaries in design time can be a headache.
Alternatively to using multiple ConcurrentDictionary<string, T> collections, or a single ConcurrentDictionary<string, object>, or the Locked<T> struct shown in Enigmativity's answer, you could just store the values in immutable and recyclable Tuple<T> instances, and store these in private volatile fields:
private static volatile Tuple<bool?> _UseGpsReceiver;
public static bool? UseGpsReceiver
{
get { return _UseGpsReceiver?.Item1; }
set { _UseGpsReceiver = new(value); }
}
private static volatile Tuple<string> _Latitude;
public static string Latitude
{
get { return _Latitude?.Item1; }
set { _Latitude = new(value); }
}
private static volatile Tuple<string> _Longitude;
public static string Longitude
{
get { return _Longitude?.Item1; }
set { _Longitude = new(value); }
}
Pros: Both the reading and the writing are lock-free. An unlimited number of readers and writers can read and update the values at the same time, without contention.
Cons: Every time a value is updated, a new Tuple<T> is instantiated, adding pressure on the .NET garbage collector. This reduces the appeal of this approach in case the values are updated too frequently. Also if you have dozens of properties like these, it might be easy to introduce subtle bugs by omitting the important volatile keyword by mistake.
Edited the code to make it thread-safe post comments
Please see the updated question at the end.
Can you please help me understand if this code is thread-safe or how it can be made thread safe?
Setup
My system has a very simple class called WorkItem.
public class WorkItem
{
public int Id {get;set;}
public string Name {get;set;}
public DateTime DateCreated {get;set;}
public IList<object> CalculatedValues {get;set;}
}
There is an interface ICalculator which has a method that takes a work item, performs a calculation and returns true.
public interface ICalculator
{
bool Calculate(WorkItem WorkItem);
}
Let's say we have two implementations of ICalculator.
public class BasicCalculator: ICalculator
{
public bool Calculate(WorkItem WorkItem)
{
//calculate some value on the WorkItem and populate CalculatedValues property
return true;
}
}
Another calculator:
public class AnotherCalculator: ICalculator
{
public bool Calculate(WorkItem WorkItem)
{
//calculate some value on the WorkItem and populate CalculatedValues property
//some complex calculation on work item
if (somevalue==0) return false;
return true;
}
}
There is a calculator handler class. Its responsibility is to execute calculators sequentially.
public class CalculatorHandler
{
public bool ExecuteAllCalculators(WorkItem task, ICalculator[] calculators)
{
bool final = true;
//call all calculators in a loop
foreach(var calculator in calculators)
{
var calculatedValue = calculator.Calculate(WorkItem);
final = final && calculatedValue;
}
return final;
}
}
Finally, in my client class, I inject ICalculators[] which are relevant for the run. I then instantiate ExecuteCalculators() method.
Now I have a large number of work items and I want to perform calculations on them so I create a list of Task, where each task is responsible of instantiating CalculatorHandler instance and then takes a work item and performs calculations by doing a WaitAll() on all of the tasks, e.g.
public class Client
{
private ICalculators[] _myCalculators;
public Client(ICalculators[] calculators)
{
_myCalculators = calculators;
}
public void ExecuteCalculators()
{
var list = new List<Task>();
for(int i =0; i <10;i++)
{
Task task = new Task(() =>
var handler = new CalculatorHandler();
var WorkItem = new WorkItem(){
Id=i,
Name="TestTask",
DateCreated=DateTime.Now
};
var result = handler.ExecuteAllCalculators(WorkItem, _myCalculators);
);
list.Add(task);
}
Task.WaitAll(list);
}
}
This is a simplied version of the system. Actual system has a range of calculators and Calculators and CalculatorHandler are injected via IoC etc.
My questions are - help me understand these points:
Each task creates a new instance of CalculatorHandler. Does this
mean anything that happens in CalculatorHandler is thread safe as it
does not have any public properties and simply loops over
calculators?
Calculators are shared amongst all tasks because they are member variable of Client class but they are passed into
CalculatorHandler which is instantiated for each task. Does it mean that when all tasks run, as new
instance of CalculatorHandler is created therefore Calculators are
automatically thread safe and we will not experience any threading issues e.g. deadlocks etc?
Can you please suggest how I can make the code threadsafe? Is it
best to pass in a Func<'ICalculators>'[] to Client class and then within each task, we can execute Func<'ICalculator'>() and then pass those instances to ICalculator there? Func<'ICalculator'> will return instance of ICalculator.
Is it true that calculators are passed in as private method variable therefore other instances of CalulatorHandler cannot run the same instance of calculator? Or because calculators are reference types, we are bound to get multi thread issues?
Update
Can you please help me understand if this updated code is thread-safe or how it can be made thread safe?
Setup
My system has a very simple class called WorkItem. It has getter public properties except 1 property "CalculatedValues".
public class WorkItem
{
public int Id {get;}
public string Name {get;}
public DateTime DateCreated {get;}
public IList<object> CalculatedValues {get;set;}
public WorkItem(int id, string name, DateTime dateCreated)
{
Id = id,
Name = name,
DateCreated = dateCreated
}
}
There is an interface ICalculator which has a method that takes a work item, performs a calculation and returns a IList. It does not change the state of work item.
public interface ICalculator
{
IList<object> Calculate(WorkItem WorkItem);
}
Let's say we have two implementations of ICalculator.
public class BasicCalculator: ICalculator
{
public IList<object>Calculate(WorkItem WorkItem)
{
//calculate some value and return List<object>
return List<object>{"A", 1};
}
}
Another calculator:
public class AnotherCalculator: ICalculator
{
public bool Calculate(WorkItem WorkItem)
{
//calculate some value and return List<object>
return List<object>{"A", 1, workItem.Name};
}
}
There is a calculator handler class. Its responsibility is to execute calculators sequentially. Note, it takes in ICalculators in its constructor when it is instantiated. It has a private static lock object too when it updates work item instance.
public class CalculatorHandler
{
private ICalculators[] _calculators;
public CalculatorHandler(ICalculators[] calculators)
{
_calculators = calculators;
}
//static lock
private static object _lock = new object();
public bool ExecuteAllCalculators(WorkItem workItem, ICalculator[] calculators)
{
bool final = true;
//call all calculators in a loop
foreach(var calculator in calculators)
{
var calculatedValues = calculator.Calculate(workItem);
//within a lock, work item is updated
lock(_lock)
{
workItem.CalculatedValues = calculatedValues;
}
}
return final;
}
}
Finally, in my client class, I execute CalculatorHandler.
Now I have a large number of work items and I want to perform calculations on them so I create a list of Task, where each task is responsible of instantiating CalculatorHandler instance and then takes a work item and performs calculations by doing a WaitAll() on all of the tasks, e.g.
public class Client
{
public void ExecuteCalculators()
{
var list = new List<Task>();
for(int i =0; i <10;i++)
{
Task task = new Task(() =>
//new handler instance and new calculator instances
var handler = new CalculatorHandler(new[]{
new BasicCalculator(), new AnotherCalculator()
});
var WorkItem = new WorkItem(
i,
"TestTask",
DateTime.Now
};
var result = handler.ExecuteAllCalculators(WorkItem);
);
list.Add(task);
}
Task.WaitAll(list);
}
}
This is a simplied version of the system. Actual system has a range of calculators and Calculators and CalculatorHandler are injected via IoC etc.
My questions are - help me understand these points:
Each task creates a new instance of CalculatorHandler and new instances of ICalculators. Calculators do not perform any I/O operations and only create a new private IList. Is calculator handler and calculator instances now thread safe?
CalculatorHandler updates work item but within a lock. Lock is a static private object. Does it mean all instances of CalculatorHandler will share one single lock and therefore at one point, only one thread can update the work item?
Work item has all public getter properties except its CalculatedValues property. CalculatedValues is only set within a static lock. Is this code now thread-safe?
1) Creating a new instance of a class, even one without public properties does not provide any guarantee of thread safety. The problem is that ExecuteAllCalculators takes two object parameters. The WorkItem object contains mutable properties and the same WorkItem object is used for all ICalculator calls. Suppose one of the calculators decides to call Clear() on WorkItem.CalculatedValues. Or suppose one calculator sets WorkItem.Name to null and the next decides to do a WorkItem.Name.Length. This isn't technically a "threading" issue because those problems can occur without multiple threads involved.
2) Calculator objects shared across threads is definitely not thread safe. Suppose one of the calculator instances uses a class level variable. Unless that variable is somehow thread protected (example: lock {...}), then it would be possible to produce inconsistent results. Depending how "creative" the implementer of the calculator instances were a deadlock could be possible.
3) Any time your code accepts interfaces you are inviting people to "play in your sandbox". It allows code that you have little control of to be executed. One of the best ways to handle this is to use immutable objects. Unfortunately, you can't change the WorkItem definition without breaking your interface contract.
4) Calculators are passed by reference. The code shows that _myCalculators is shared across all tasks created. This doesn't guarantee that you will have problems, it only makes it possible that you might have problems.
No, it is not thread-safe. If there is any shared state in any calculation then the it is possible to have threading issues. The only way to avoid threading issues is to ensure you are not updating any shared state. That means read-only objects and/or using "pure" functions.
You've used the word "shared" - that means not thread-safe by virtue of sharing state. Unless you mean "distributed" rather than "shared".
Exclusively use read-only objects.
They are reference types so they may be shared amongst separate threads - hence not thread-safe - unless they are read-only.
Here's an example of a read-only object:
public sealed class WorkItem : IEquatable<WorkItem>
{
private readonly int _id;
private readonly string _name;
private readonly DateTime _dateCreated;
public int Id { get { return _id; } }
public string Name { get { return _name; } }
public DateTime DateCreated { get { return _dateCreated; } }
public WorkItem(int id, string name, DateTime dateCreated)
{
_id = id;
_name = name;
_dateCreated = dateCreated;
}
public override bool Equals(object obj)
{
if (obj is WorkItem)
return Equals((WorkItem)obj);
return false;
}
public bool Equals(WorkItem obj)
{
if (obj == null) return false;
if (!EqualityComparer<int>.Default.Equals(_id, obj._id)) return false;
if (!EqualityComparer<string>.Default.Equals(_name, obj._name)) return false;
if (!EqualityComparer<DateTime>.Default.Equals(_dateCreated, obj._dateCreated)) return false;
return true;
}
public override int GetHashCode()
{
int hash = 0;
hash ^= EqualityComparer<int>.Default.GetHashCode(_id);
hash ^= EqualityComparer<string>.Default.GetHashCode(_name);
hash ^= EqualityComparer<DateTime>.Default.GetHashCode(_dateCreated);
return hash;
}
public override string ToString()
{
return String.Format("{{ Id = {0}, Name = {1}, DateCreated = {2} }}", _id, _name, _dateCreated);
}
public static bool operator ==(WorkItem left, WorkItem right)
{
if (object.ReferenceEquals(left, null))
{
return object.ReferenceEquals(right, null);
}
return left.Equals(right);
}
public static bool operator !=(WorkItem left, WorkItem right)
{
return !(left == right);
}
}
Once created it can't be modified so thread-safety is no longer an issue.
Now, if I can assume that each ICalculator is also implemented without state, and thus is a pure function, then the calculation is thread-safe. However, there is nothing in your question that let's me know that I can make this assumption. There is no way, because of that, that anyone can tell you that your code is thread-safe.
So, given the read-only WorkItem and the pure ICalculator function, then the rest of your code then looks like it would be perfectly fine.
I use ConcurrentDictionary to collect data in memory in web api application. Using api methods I add and update objects in ConcurrentDictionary. And there is background thread which analyze and clean up this dictionary based on object properties. Now I'm considering two approaches:
1. use lock on dictionary item in updateValueFactory in AddOrUpdate method, but question is how to read properties properly to be sure I have the latest version of it and that I'm not reading property in not stable state.
public class ThreadsafeService2
{
private readonly ConcurrentDictionary<string, ThreadSafeItem2> _storage =
new ConcurrentDictionary<string, ThreadSafeItem2>();
public void AddOrUpdate(string name)
{
var newVal = new ThreadSafeItem2();
_storage.AddOrUpdate(name, newVal, (key, oldVal) =>
{
//use lock
lock (oldVal)
{
oldVal.Increment();
}
return oldVal;
});
}
public void Analyze()
{
foreach (var key in _storage.Keys)
{
if (_storage.TryGetValue(key, out var item))
{
//how to read it properly?
long ticks = item.ModifiedTicks;
}
}
}
}
public class ThreadSafeItem2
{
private long _modifiedTicks;
private int _counter;
public void Increment()
{
//no interlocked here
_modifiedTicks = DateTime.Now.Ticks;
_counter++;
}
//now interlocked here
public long ModifiedTicks => _modifiedTicks;
public int Counter => _counter;
}
2. use Interlocked and memory barriers on property level without lock, looks a bit verbose for me.
public class ThreadsafeService1
{
private readonly ConcurrentDictionary<string, ThreadSafeItem1> _storage =
new ConcurrentDictionary<string, ThreadSafeItem1>();
public void AddOrUpdate(string name)
{
var newVal = new ThreadSafeItem1();
_storage.AddOrUpdate(name, newVal, (key, oldVal) =>
{
//no lock here
oldVal.Increment();
return oldVal;
});
}
public void Analyze()
{
foreach(var key in _storage.Keys)
{
if(_storage.TryGetValue(key, out var item))
{
//reading through interloacked
long ticks = item.ModifiedTicks;
}
}
}
}
public class ThreadSafeItem1
{
private long _modifiedTicks;
private int _counter;
public void Increment()
{
//make changes in atomic manner
Interlocked.Exchange(ref _modifiedTicks, DateTime.Now.Ticks);
Interlocked.Increment(ref _counter);
}
public long ModifiedTicks => Interlocked.Read(ref _modifiedTicks);
public int Counter => Thread.VolatileRead(ref _counter);
}
What is the best practices here?
So both of your implementations have major problems. The first solution locks when incrementing, but doesn't lock when reading, meaning the other places accessing the data can read invalid state.
A non-technical problem, but a major issue nonetheless, is that you've named your class ThreadSaveItem and yet it's not actually designed to be accessed safely from multiple threads. It's the callers responsibility, in this implementation, to ensure that the item isn't accessed from multiple threads. If I see a class called ThreadSafeItem I'm going to assume it's safe to access it from multiple threads, and that I don't need to synchronize my access to it so long as each operation I perform is the only thing that needs to be logically atomic.
Your Interlocked solution is problematic in that you have to fields that you're modifying, that are conceptually tied together, but you don't synchronize their changes together, meaning someone can observe a modification to one and not the other, which is a problem for that code.
Next, your use of AddOrUpdate in both solutions isn't really appropriate. The whole point of the method call is to add an item or replace it with another item, not to mutate the provided item (that's why it takes a return value; you're supposed to produce a new item). If you want to go with the approach of getting a mutable item and mutating it, the way to go would be to call GetOrAdd to either get an existing item or create a new one, and then to mutate it in a thread safe manner using the returned value.
The whole solution is radically simplified by simply making ThreadSafeItem immutable. It lets you use AddOrUpdate on the ConcurrentDictionary for the update, and it means that the only synchronization that needs to be done is the updating of the value of the ConcurrentDictionary, and it already handles synchronization of its own state, no synchronization needs to be done at all when accessing ThreadSafeItem, because all access to the data is inherently thread safe because it's immutable. This means that you never actually need to write any synchronization code at all, which is exactly what you want to strive for whenever possible.
And finally, we have the actual code:
public class ThreadsafeService3
{
private readonly ConcurrentDictionary<string, ThreadSafeItem3> _storage =
new ConcurrentDictionary<string, ThreadSafeItem3>();
public void AddOrUpdate(string name)
{
_storage.AddOrUpdate(name, _ => new ThreadSafeItem3(), (_, oldValue) => oldValue.Increment());
}
public void Analyze()
{
foreach (var pair in _storage)
{
long ticks = pair.Value.ModifiedTicks;
//Note, the value may have been updated since we checked;
//you've said you don't care and it's okay for a newer item to be removed here if it loses the race.
if (isTooOld(ticks))
_storage.TryRemove(pair.Key, out _);
}
}
}
public class ThreadSafeItem3
{
public ThreadSafeItem3()
{
Counter = 0;
}
private ThreadSafeItem3(int counter)
{
Counter = counter;
}
public ThreadSafeItem3 Increment()
{
return new ThreadSafeItem3(Counter + 1);
}
public long ModifiedTicks { get; } = DateTime.Now.Ticks;
public int Counter { get; }
}
The solution proposed by Servy (using an immutable Item type) is probably the best solution for your scenario. I would also suggest switching from class to readonly struct for reducing the allocations, although the ConcurrentDictionary is probably going to wrap the struct in a reference-type Node internally, so you might not gain anything from this.
For the sake of completeness I will propose an alternative solution, which is to use the GetOrAdd instead of the AddOrUpdate, and lock on the Item whenever you are doing anything with it:
public class Item // Mutable and thread-unsafe
{
public long ModifiedTicks { get; private set; }
public int Counter { get; private set; }
public void Increment()
{
ModifiedTicks = DateTime.Now.Ticks;
Counter++;
}
}
public class Service
{
private readonly ConcurrentDictionary<string, Item> _storage = new();
public void AddOrUpdate(string name)
{
Item item = _storage.GetOrAdd(name, _ => new());
lock (item) item.Increment(); // Dont't forget to lock!
}
public void Analyze()
{
foreach (var (key, item) in _storage.ToArray())
{
lock (item) // Dont't forget to lock!
{
long ticks = item.ModifiedTicks;
}
}
}
}
This solution offers probably the best performance, but the burden of remembering to lock correctly everywhere cannot be underestimated.
I can't comment on the specifics of what exactly you are doing, but interlock and Concurrent dictionary is better than locks you do yourself.
I would question this approach though. Your data is important enough, but not so important to persist it? Depending on the usage of the application this approach will slow it down by some degree. Again, not knowing exactly what you are doing, you could throw each "Add" into an MSMQ, and then have an external exe run at some schedule to process the items. The website will just fire and forget, with no threading requirements.
Say we have a POD type:
private class Messages {
public byte[] last;
public byte[] next;
}
and its instance messages.
When a user (caller) requests instance we want to give him deep copy of messages object (that can be not the latest). When a user sets his own version we want to provide it to others as sun as possible yet not interrupting read requests (older version should be removed, not interrupting reads as soon as possible).
How to do such object versioning using System.Collections.Concurrent?
What have I tried:
internal class CuncurrentMessagesHelper {
private readonly ConcurrentStack<Messages> _stack = new ConcurrentStack<Messages>();
public CuncurrentMessagesHelper() {
}
public void SetLatest(Messages m) {
var length = _stack.Count;
_stack.Push(m);
var range = new Messages[length];
_stack.TryPopRange(range, 0, length);
}
public bool ReadLatest(out Messages result) {
return _stack.TryPeek(out result);
}
}
Yet such helper approach seems as ugly hack.
because even we know result is garanteed we use try and return bool instead of object;
it TryPopRange makes us create addintional array with size of all previous versions.
This isn't POD. It's a POCO. I suggest you read up on the difference between .NET's value types and reference types, since their semantics are crucial while writing safe concurrent code.
Since C# references are guaranteed to be atomic, the solution is simple (and doesn't require any special concurrent containers).
Assuming your Messages object is immutable once passed in:
internal class ConcurrentMessagesHelper {
private volatile Messages _current;
public void SetLatest(Messages m) {
_current = m;
}
public Messages ReadLatest() {
return _current;
}
}
Note that it's the reference to the object that's being copied here (atomically), and not the object's byte[] fields. volatile is required since the reference is accessed by multiple threads (it ensures correct behaviour, in particular with regards to memory ordering and limiting the optimizations the JIT can perform to only thread-safe ones).
If the Messages object passed to SetLatest can change while it's the latest, then all you have to do is make a copy first. SetLatest becomes:
public void SetLatest(Messages m) {
_current = DeepClone(m);
}
If readers are allowed to change the Messages object returned, then you have to copy it before letting them have it too. ReadLatest becomes:
public Messages ReadLatest() {
return DeepClone(_current);
}
Note that if the values contained in the byte[] fields of Messages are immutable during each message's lifetime, all you need is a shallow copy, not a deep one.
You can make the interface even nicer by wrapping it in a simple property:
internal class ConcurrentMessagesHelper {
private volatile Messages _current;
public Messages Current {
get { return DeepClone(_current); }
set { _current = DeepClone(value); }
}
private static Messages DeepClone(Messages m)
{
if (m == null)
return null;
return new Messages {
last = m.last == null ? null : (byte[])m.last.Clone(),
next = m.next == null ? null : (byte[])m.next.Clone()
};
}
}
If you actually did have a POD type (e.g. struct Messages), then I suggest the simplest solution would be to wrap it in a class so you can have an atomic reference to a copy of it, which would allow you to use the solution above. StrongBox<T> comes to mind.
The code in such a case becomes even simpler, because no explicit copying is required:
private struct Messages {
public byte[] last;
public byte[] next;
}
internal class ConcurrentMessagesHelper {
private volatile StrongBox<Messages> _current;
public Messages Current {
get { return _current.Value; }
set { _current = new StrongBox<Messages>(value); }
}
}
If the byte arrays in Messages can change during the object's lifetime, then we still need the deep cloning, though:
internal class ConcurrentMessagesHelper {
private volatile StrongBox<Messages> _current;
public Messages Current {
get { return DeepClone(_current.Value); }
set { _current = new StrongBox<Messages>(DeepClone(value)); }
}
private static Messages DeepClone(Messages m)
{
return new Messages {
last = m.last == null ? null : (byte[])m.last.Clone(),
next = m.next == null ? null : (byte[])m.next.Clone()
};
}
}
Often, when I want a class which is thread-safe, I do something like the following:
public class ThreadSafeClass
{
private readonly object theLock = new object();
private double propertyA;
public double PropertyA
{
get
{
lock (theLock)
{
return propertyA;
}
}
set
{
lock (theLock)
{
propertyA = value;
}
}
}
private double propertyB;
public double PropertyB
{
get
{
lock (theLock)
{
return propertyB;
}
}
set
{
lock (theLock)
{
propertyB = value;
}
}
}
public void SomeMethod()
{
lock (theLock)
{
PropertyA = 2.0 * PropertyB;
}
}
}
It works, but it is very verbose. Sometimes I even create a lock object for each method and property creating more verbosity and complexity.
I know that it is also possible to lock classes using the Synchronization attribute but I'm not sure how well that scales -- as I often expect to have hundreds of thousands, if not millions, of instances of thread-safe objects. This approach would create a synchronization context for every instance of the class, and requires the class to be derived from ContextBoundObject and therefore could not be derived from anything else -- since C# doesn't allow for multiple inheritance -- which is a show stopper in many cases.
Edit: As several of the responders have emphasized, there is no "silver bullet" thread-safe class design. I'm just trying to understand if the pattern I'm using is one of the good solutions. Of course the best solution in any particular situation is problem dependent. Several of the answers below contain alternative designs which should be considered.
Edit: Moreover, there is more than one definition of thread safety. For example, in my implementation above, the following code would NOT be thread-safe:
var myObject = new ThreadSafeClass();
myObject.PropertyA++; // NOT thread-safe
So, does the class definition above represent a good approach? If not, what would you recommend for a design with similar behavior which would be thread-safe for a similar set of uses?
There is no "one-size-fits-all" solution to the multi-threading problem. Do some research on creating immutable classes and learn about the different synchronization primitives.
This is an example of a semi-immutable or the-programmers-immutable class .
public class ThreadSafeClass
{
public double A { get; private set; }
public double B { get; private set; }
public double C { get; private set; }
public ThreadSafeClass(double a, double b, double c)
{
A = a;
B = b;
C = c;
}
public ThreadSafeClass RecalculateA()
{
return new ThreadSafeClass(2.0 * B, B, C);
}
}
This example moves your synchronization code into another class and serializes access to an instance. In reality, you don't really want more than one thread operating on an object at any given time.
public class ThreadSafeClass
{
public double PropertyA { get; set; }
public double PropertyB { get; set; }
public double PropertyC { get; set; }
private ThreadSafeClass()
{
}
public void ModifyClass()
{
// do stuff
}
public class Synchronizer
{
private ThreadSafeClass instance = new ThreadSafeClass();
private readonly object locker = new object();
public void Execute(Action<ThreadSafeClass> action)
{
lock (locker)
{
action(instance);
}
}
public T Execute<T>(Func<ThreadSafeClass, T> func)
{
lock (locker)
{
return func(instance);
}
}
}
}
Here is a quick example of how you would use it. It may seem a little clunky but it allows you to execute many actions on the instance in one go.
var syn = new ThreadSafeClass.Synchronizer();
syn.Execute(inst => {
inst.PropertyA = 2.0;
inst.PropertyB = 2.0;
inst.PropertyC = 2.0;
});
var a = syn.Execute<double>(inst => {
return inst.PropertyA + inst.PropertyB;
});
I know this might sound like an smart a** answer but ... the BEST way to develop threadsafe classes is to actually know about multithreading, about its implications, its intricacies and what does it implies. There's no silver bullet.
First you need a good reason to use it. Threads are a tool, you don't want to hit everything with your new found hammer.
Secondly, learn about the problems of multithreading... deadlocks, race conditions, starvation and so on
Third, make sure is worth it. I'm talking about benefit/cost.
Finally... be prepared to heavy debugging. Debugging multithreaded code is much more difficult than standard old sequential code. Learn some techniques about how to do that.
Seriously... don't try to multithread (in production scenarios I mean) until you know what you're getting yourself into... It can be a huge mistake.
Edit: You should of course know the synchronization primitives of both the operating system and your language of choice (C# under Windows in this case, I guess).
I'm sorry I'm not giving just the code to just make a class threadsafe. That's because it does not exist. A completely threadsafe class will probably just be slower than just avoiding threads and will probably act as a bottleneck to whatever you're doing... effectively undoing whatever you thing you're achieving by using threads.
Bear in mind that the term "thread safe" is not specific; what you're doing here would be more accurately referred to as "synchronization" through the use of a Monitor lock.
That said, the verbosity around synchronized code is pretty much unavoidable. You could cut down on some of the whitespace in your example by turning things like this:
lock (theLock)
{
propertyB = value;
}
into this:
lock (theLock) propertyB = value;
As to whether or not this is the right approach for you we really need more information. Synchronization is just one approach to "thread safety"; immutable objects, semaphores, etc. are all different mechanisms that fit different use-cases. For the simple example you provide (where it looks like you're trying to ensure the atomicity of a get or set operation), then it looks like you've done the right things, but if your code is intended to be more of an illustration than an example then things may not be as simple.
Since no else seems to be doing it, here is some analysis on your specific design.
Want to read any single property? Threadsafe
Want to update to any single property? Threadsafe
Want to read a single property and then update it based on its original value? Not Threadsafe
Thread 2 could update the value between thread 1's read and update.
Want to update two related properties at the same time? Not Threadsafe
You could end up with Property A having thread 1's value and Property B having thread 2's value.
Thread 1 Update A
Thread 2 Update A
Thread 1 Update B
Thread 2 Update B
Want to read two related properties at the same time? Not Threadsafe
Again, you could be interrupted between the first and second read.
I could continue, but you get the idea. Threadsafety is purely based on how you plan to access the objects and what promises you need to make.
You may find the Interlocked class helpful. It contains several atomic operations.
One thing you could do that could help you avoid the extra code is use something like PostSharp to automatically inject those lock statements into your code, even if you had hundreds of them. All you'd need is one attribute attached to the class, and the attribute's implementation which would add the extra locking variables.
As per my comment above - it gets a little hairier if you want simultaneous readers allowed but only one writer allowed. Note, if you have .NET 3.5, use ReaderWriterLockSlim rather than ReaderWriterLock for this type of pattern.
public class ThreadSafeClass
{
private readonly ReaderWriterLock theLock = new ReaderWriterLock();
private double propertyA;
public double PropertyA
{
get
{
theLock.AcquireReaderLock(Timeout.Infinite);
try
{
return propertyA;
}
finally
{
theLock.ReleaseReaderLock();
}
}
set
{
theLock.AcquireWriterLock(Timeout.Infinite);
try
{
propertyA = value;
}
finally
{
theLock.ReleaseWriterLock();
}
}
}
private double propertyB;
public double PropertyB
{
get
{
theLock.AcquireReaderLock(Timeout.Infinite);
try
{
return propertyB;
}
finally
{
theLock.ReleaseReaderLock();
}
}
set
{
theLock.AcquireWriterLock(Timeout.Infinite);
try
{
propertyB = value;
}
finally
{
theLock.ReleaseWriterLock();
}
}
}
public void SomeMethod()
{
theLock.AcquireWriterLock(Timeout.Infinite);
try
{
theLock.AcquireReaderLock(Timeout.Infinite);
try
{
PropertyA = 2.0 * PropertyB;
}
finally
{
theLock.ReleaseReaderLock();
}
}
finally
{
theLock.ReleaseWriterLock();
}
}
}