Created
June 14, 2018 02:28
-
-
Save dancrowley303/8b0cf0b5d9701163d2cdb031f3d3102a to your computer and use it in GitHub Desktop.
thread safe data structure access strategies
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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