Hi,
I have a code that sometimes need to run in single threaded environment (STE) and sometimes in multi threaded environment (MTE). In the MTE I have to set locks in order to synchronize the objects and in the STE I need to avoid locks since it is time consuming and will affect performance.
Implementation
To solve this I created a new lock mechanism:
I created an interface named ILocker:
public interface ILocker : IDisposable
{
ILocker Lock();
}
This interface has two implementations:
One that implements a lock, for the MTE:
public class Locker : ILocker
{
private readonly object _lock = new object();
public ILocker Lock()
{
Monitor.Enter(_lock);
return this;
}
public void Dispose()
{
Monitor.Exit(_lock);
}
}
And another one that does nothing, for the STE
public class NoOpLocker : ILocker
{
public ILocker Lock()
{
return this;
}
public void Dispose()
{
}
}
Usage
An original code of this form:
object locker = new object();
lock(locker) { ... }
Will look like:
ILocker locker = new Locker(); // or NoOpLocker();
using (locker.Lock()) { ... }
Performance
I ran 100,000,000 iterations on one thread for each locking and checked how long it takes. The test function looks like this:
void CheckLocker(ILocker locker)
{
Stopwatch stopwatch = Stopwatch.StartNew();
for (int i = 0; i < 100000000; i++)
{
using (locker.Lock())
{
DoNothing();
}
}
Console.WriteLine(stopwatch.ElapsedMilliseconds);
}
void DoNothing() { /* Do nothing */ }
The results were:
Lock type | Time in milliseconds |
No locks | 10 |
using(..) with NoOpLocker | 775 |
lock(..) | 4865 |
using(..) with Locker | 6603 |
Pros
- The type of lock can be determined at run time.
- The change from lock(..) to using(..) is simple.
- A class can be written with MTE in mind and can be used for STE when needed without rewriting the class.
- A class that is already written with lock(..) and used also in STE, can use using(..) and improve performance, while still supporting MTE as needed.
Cons
- The Locker works slower than just using lock(..)
- The NoOpLocker works slower than using nothing.
No comments:
Post a Comment