Skip to content

Instantly share code, notes, and snippets.

@dancrowley303
Created June 14, 2018 02:28
Show Gist options
  • Save dancrowley303/8b0cf0b5d9701163d2cdb031f3d3102a to your computer and use it in GitHub Desktop.
Save dancrowley303/8b0cf0b5d9701163d2cdb031f3d3102a to your computer and use it in GitHub Desktop.
thread safe data structure access strategies
using System;
using System.Threading;
using System.Threading.Tasks;
namespace VolatileTrap
{
class Widget
{
private long count = 0;
public long Count
{
get { return count; }
}
public void Increment()
{
count++;
}
}
class VolatileWidget
{
//only guarantees safety for *atomic* operations
//increments are ready/modify/write cycles, so they won't be consistent
private volatile int count = 0;
public long Count
{
get { return count; }
}
public void Increment()
{
count++;
}
}
class InterlockingWidget
{
private long count = 0;
public long Count
{
get { return Interlocked.Read(ref count); }
}
internal void Increment()
{
Interlocked.Increment(ref count);
}
}
class LockingWidget
{
private long count = 0;
private object token = new Object();
public long Count
{
get
{
//locks are thread safe but they are slow
lock (token)
{
return count;
}
}
}
public void Increment()
{
lock (token)
{
count++;
}
}
}
class Program
{
static void Main(string[] args)
{
var cts = new CancellationTokenSource();
var count1 = 0;
var count2 = 0;
var w = new Widget();
var vw = new VolatileWidget();
var lw = new LockingWidget();
var iw = new InterlockingWidget();
var tasks = new Task[2];
tasks[0] = Task.Run(() =>
{
while (!cts.IsCancellationRequested)
{
w.Increment();
vw.Increment();
lw.Increment();
iw.Increment();
count1++;
}
}, cts.Token);
tasks[1] = Task.Run(() =>
{
while (!cts.IsCancellationRequested)
{
w.Increment();
vw.Increment();
lw.Increment();
iw.Increment();
count2++;
}
}, cts.Token);
Task.WaitAll(tasks, 1000);
cts.Cancel();
Console.WriteLine($@"expected increments are {count1 + count2}");
Console.WriteLine($@"actual widget increments are {w.Count}");
Console.WriteLine($@"actual volatile widget increments are {vw.Count}");
Console.WriteLine($@"actual locking widget increments are {lw.Count}");
Console.WriteLine($@"actual interlocking widget increments are {iw.Count}");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment