I'm trying to track down a bug that I think might be related to the applications multithreading. I've simplified the code below:
class Outer {
private static int count;
//this function is called from multiple threads in quick succession
public void DoFoo() {
Inner.Increment(ref count);
}
}
class Inner {
private readonly static object mLock = new object();
public static string Increment(ref count) {
lock (mLock) (
if (count > 1000)
count = 0;
count++;
}
return count.ToString();
}
}
Can the locking guarantee the safety of a variable passed in that way? Is there any copying of count going on that seems non-obvious and may break the memory safety? I was thinking it might return a new int and do the assignment at the end of the method or something. Apart from that it's my understanding that the lock section would handle any caching issues.
The error which bought the issue to our attention was seemingly one of the threads having a stale version of count.
The problem here is that some other thread could read directly Outer.count when it is == 0, because you can access Outer.count without first having obtained a lock (normally as written in your code, count can be 0 only before the first call to Inner.Increment, from then on it can only have a value between 1 and 1001)
Lockless can be done in this way:
class Inner
{
public static string Increment(ref int count)
{
while (true)
{
int original = count;
int next = original;
if (next > 1000)
{
next = 0;
}
next++;
if (Interlocked.CompareExchange(ref count, next, original) == original)
{
return next.ToString();
}
}
}
}
I'm calculating a next value and using it (through Interlocked.CompareExchange) only if count hasn't changed in the meantime.
Related
Hello i want to ask how to modifiying value static variable from static callback, and read value again. I need to stop while looping when value from static variable change. This is my code.
The problem is value from stepControlEx remain same, it doesnt change when another callback run again and modify the value. It makes my looping stuck and cannot end.
Thanks for helping
Private static int stepControl = 0;
Private static int stepControlEx
{
get { return stepControl;}
set { stepControl = value;}
}
Private static void CallbackHandle (Object object)
{
If (object == 0)
{
stepControlEx = 0;
While (stepControlEx == 0)
{
//do events
//stop when stepControl Change
}
}
Else If (object == 1)
{
stepControlEx = 1;
While (stepControlEx == 1)
{
//do events
//stop when stepControl Change
}
}
}
EDITED (SOLVED):
I tottaly change the algorithm and use thread that process data from queue. Callback function only enqueue input to queue and thread dequeue input to processing, now step control doesn't need as global variable. Thank you
Your code looks ambiguous. But I have only one comment for your code. If you have a static variable and shared among multiple threads, you need to lock the variable while changing it.
I think you get deadlocks that is why the loop never ends.
Anytime you assign any static variable in a multi-threading environment. you need to to this:
lock (new object())
{
stepControlEx = 0;
}
I have the following class:
public class AtomicLong
{
private long initial;
private long value;
public AtomicLong(long value = 0)
{
this.initial = value;
this.value = value;
}
public class Handle : IDisposable
{
private AtomicLong source;
private long amount;
public Handle(AtomicLong source, long amount)
{
this.source = source;
this.amount = amount;
}
public void Dispose()
{
if (source == null)
return;
Interlocked.Add(ref source.value, amount);
source = null;
}
}
public Handle Claim(long amount)
{
if (amount > initial)
throw new ArgumentOutOfRangeException("amount", amount, "Must be no more than the initial amount.");
if (amount < 0)
throw new ArgumentOutOfRangeException("amount", amount, "Must be nonnegative.");
while (true)
{
var oldValue = Interlocked.Read(ref value);
var newValue = oldValue - amount;
if (newValue >= 0 &&
oldValue == Interlocked.CompareExchange(ref value, newValue, oldValue))
{
return new Handle(this, amount);
}
}
}
}
An example usage of this is that I can have a single AtomicLong unusedMemory which represents the current number of bytes of memory available to a set of workers. (It's not meant to be anywhere near exact - it's just a rough measure.) I then do this on a bunch of different worker threads:
while (true)
{
var unitOfWork = WaitForUnitOfWork();
long requiredMemory = unitOfWork.RequiredMemory;
using (var handle = unusedMemory.Claim(requiredMemory))
{
//wait until requireMemory can be claimed from unusedMemory
//do work with reserved memory, represented by handle
//when handle disposes, memory is released back to the unusedMemory
}
}
The problem with my AtomicLong class is that calls to Claim will busy-wait until they return. I'd like to fix this by using some kind of OS-level wait handle abstraction.
Can you suggest how I could go about doing that?
Motivation
Consider the following scenario:
unusedMemory starts with an initial value of 10GB (10 << 30)
100 worker threads
10 units of work, each taking 10GB and 1 minute to perform
first worker calls Claim(10 << 30) and it nearly-immediately returns
it begins doing work that will finish after 1 minute
some 9 other workers make an identical call to Claim(10 << 30) and do a "bad" busy wait for 1 minute
9 threads doing something like a while(true){/*do nothing*/} loop in the Claim method!
lots of needless CPU usage
the rest of the workers (90) do a "good" OS-level wait in the WaitForUnitOfWork() method
The important point: Claim is only "cheap" if the requested amount of memory is actually available to be claimed. If it isn't, busy-waiting happens until it is available.
Just to be entirely clear, in the Claim method, I'm pointing out the exact expression which makes all the difference (newValue >= 0):
while (true)
{
var oldValue = Interlocked.Read(ref value);
var newValue = oldValue - amount;
if (newValue >= 0 && // <--------------------------- THIS IS THE PROBLEM
oldValue == Interlocked.CompareExchange(ref value, newValue, oldValue))
{
return new Handle(this, amount);
}
}
The question is not about whether Interlocked.CompareExchange is going to be expensive - I'm aware it's cheap. The question is about how to deal with the busy-waiting that occurs in the case when the amount a caller wants to Claim is currently greater than the amount in the AtomicLong.
If you have a completely different approach to solving this kind of problem, or see some flaw in what I already have, I'd like to hear about that too!
You have several options.
For instance, you can create a smarter busy-wait, by putting the active thread to sleep for a given time interval, so it doesn't always check your condition, but it does it periodically.
Another solution is to create a custom event and wait for that event in your active thread, and you can define a custom event which will fulfill your task I believe.
You can read more about events here. You can read about custom event creation here.
Here's the solution I came up with:
Parameters
obj: the synchronization object used by Monitor
pollIterval: the rate at which calls will poll until a successful transaction attempt
value: the value being modified by the transaction
precondition: an optional condition that must be true at the start of the transaction
transform: the operation that changes the value
postcondition: an optional condition that must be true at the end of the transaction
Code
public static class AtomicHelper
{
public static void LongTransaction(
object obj,
TimeSpan pollInterval,
ref long value,
Func<long, bool> precondition,
Func<long, long> transform,
Func<long, bool> postcondition)
{
while (true)
{
var oldValue = Interlocked.Read(ref value);
if (precondition != null && !precondition(oldValue))
{
Monitor.Wait(obj, pollInterval);
continue;
}
var newValue = transform(oldValue);
if (postcondition != null && !postcondition(newValue))
{
Monitor.Wait(obj, pollInterval);
continue;
}
if (Interlocked.CompareExchange(ref value, newValue, oldValue) == oldValue)
{
Monitor.PulseAll(obj);
return;
}
}
}
}
Example Usage
long n = 10;
object obj = new object();
//On many different threads, run this concurrently:
AtomicHelper.LongTransaction(
obj,
TimeSpan.FromSeconds(1),
ref n,
null,
x => x - 1,
x => x >= 0);
Thread.Sleep(TimeSpan.FromSeconds(3));
AtomicHelper.LongTransaction(
obj,
TimeSpan.Zero,
ref n,
null,
x => x + 1,
null);
I am attempting to model slot machine behavior with parallel programming, using a base class (SlotBase) which will be overridden by classes representing each individual machine.
In the base class, I have a method that (attempts to) invoke a descendant class's method (marked abstract in the base class) that plays a sample and returns results through use of output parameters, and then using a mutually exclusive lock, updates the base class's summation variables.
Relevant code samples as follows:
From SlotBase.cs:
#region Member Variables
protected long m_CoinIn;
protected long[] m_CoinOut;
protected string[] m_FeatureList;
protected long[] m_HitCount;
// .. and many more, but redacted for length
#endregion
protected abstract void PlaySample(long sampleSize, out long coinIn, out long[] coinOut, out long[] hitCount);
protected override void DoSimulation() {
// No need to intialize these, as the calling routine will, and only it knows how big the arrays need to be, and so forth.
object mutex = new object();
if (ParallelMode) {
int periodCount = (int)(BatchSize / PeriodSize);
Parallel.For(0, periodCount, delegate(int i) {
long coinIn;
long[] coinOut;
long[] hitCount;
PlaySample(PeriodSize, out coinIn, out coinOut, out hitCount);
lock (mutex) {
Console.WriteLine("Coin in this batch: {0}", coinIn);
m_CoinIn += coinIn;
for (int j = 0; j < m_FeatureList.Length; ++j) {
m_CoinOut[j] += coinOut[j];
m_HitCount[j] += hitCount[j];
}
}
});
}
}
.. and from a typical subclass implementation:
protected override void PlaySample(long sampleSize, out long coinIn, out long[] coinOut, out long[] hitCount) {
switch (WagerIndex) {
case (int)WagerType.Main: {
RNG localRNG = SpawnRNG();
coinIn = 0;
coinOut = new long[m_FeatureList.Length];
hitCount = new long[m_FeatureList.Length];
for (long iter = 0; iter < sampleSize; ++iter) {
coinIn += m_LinesPlayed;
double[] output = GetSpinResults(ref localRNG, (int)SpinMode.MainSpin);
for (int i = 0; i < m_FeatureList.Length; ++i) {
coinOut[i] += (long)output[i];
if (output[i] > 0) ++hitCount[i];
}
}
break;
}
default: {
throw new Exception(string.Format("Wager Type index {0} not supported", WagerIndex));
}
}
}
.. this actually works quite effectively with small values of SampleSize and PeriodSize but quickly proceeds to hang (or virtually hang) as values increase.
I've tried commenting out the variable updates and the hanging continues in earnest, which suggests that the problem is in fact with the way I'm implementing the Parallel.For loop.
I have no problems tearing this down pretty much from scratch and rebuilding to get this working. My only really important design goal in that I have the same paradigm (one base class, multiple sub-classes for implementation of different slots).
Where am I going wrong?
upd: Let me rephrase my question shortly.
There are N double numbers. There are N dedicated threads each of them update own double number (_cachedProduct in the example below).
Somehow I need to have sum of these numbers and I need IndexUpdated event to be raised ASAP after any double number is changed (it would be nice if such event can be raised in 10 µs or less).
Below is how I tried to implement this task
===============================================
To calculate stock exchange index I create private double[] _cachedProduct; field. These field is written
by many threads
// called from another threads
public override void InstrumentUpdated(Instrument instrument)
{
if (!_initialized)
{
if (!Initialize())
{
return;
}
}
int instrumentId = instrument.Id;
OrderBook ob = Program.market.OrderBook(instrument);
if (ob.MedianOrAskOrBid == null)
{
_cachedProduct[instrumentId] = 0;
}
else
{
_cachedProduct[instrumentId] = ((double) ob.MedianOrAskOrBid)*_ammounts[instrumentId];
}
}
_ammounts is pre-initialized array and please ignore Initialize method and variable - they just works.
In loop I just sum all _cachedProduct and when values changes I notify others.
Task.Factory.StartNew(() =>
{
while(true)
{
if (_initialized)
{
break;
}
}
while (true)
{
CalculateAndNotify();
//Thread.Sleep(5);
}
}
, TaskCreationOptions.LongRunning);
protected void CalculateAndNotify()
{
var oldValue = Value;
Calculate();
if (oldValue != Value)
{
NotifyIndexChanged();
}
}
protected override void Calculate()
{
double result = 0;
for (int i = 0; i < _instrumentIds.Count(); i++)
{
int instrumentId = _instrumentIds[i];
if (_cachedProduct[instrumentId] == 0)
{
Value = null;
return;
}
result += _cachedProduct[instrumentId];;
}
Value = result;
}
I must use Interlocked to update my double _cachedProduct values but please ignore that fact now, what other problems with this code do you see?
Should I call Calculate method inside while(true) so I always use one core without delays. My machine has 24 cores so I was thinking this is ok.
However without Thread.Sleep(5) (commented) I do see significant slow-down in the program overall and I do not understand why. Program executes several dozens times slower in many places.
The question is if my idea of using while(true) without any locking at all is OK. Or should I introduce some locking method so I would only Calculate index when one of of _cachedProduct is updated?
I think you might get better performance and clearer code if you do not use an extra thread and loop for your sum. On every change to an instrument you calculate the difference and immediately update the index and perform the notify
So if a thread calls InstrumentUpdated for a single instrument;
change = newvalue - currentvalue;
// used interlocked here to change the index threadsafe
StockExchangeSum = Interlocked.Add(ref StockExchangeSum,change);
NotifyIndexChanged();
Can double[] be a more complex type?
How does WaitHandle.WaitAny compare performance wise?
Something like as follows.
private Index[] indicies;
public class Index
{
public WaitHandle Updated =
new EventWaitHandle(false, EventResetMode.AutoReset);
public double _value;
public double Value
{
get {return _value;}
set
{
if(_value != value)
{
_value = value;
Updated.Set();
}
}
}
}
TaskFactory.StartNew(() =>
{
while(true)
{
WaitHandle.Any(indicies.Select(i => i.Updated));
CalculateAndNotify();
}
});
Some points for you to think about
Have you tried profiling your calculation block in isolation to the rest of the code? I noticed this in your Calculate function:
for (int i = 0; i < _instrumentIds.Count(); i++)
_instrumentIds.Count() invokes an iteration over the entire collection and it is possible this is invoked for each trip around the loop. i.e. you are doing N^2/2 iterations of _instrumentIds
Is the _instrumentIdsIEnumerable being modified during this calculation operation? If so you could get all sorts of race conditions leading to incorrect answers.
Is the Task containing CalculateAndNotify called once or is it called many times (nested)? E.g. is there some operation inside CalculateAndNotify that could cause it to be triggered recursively?
If so, you might find you have several calculations performing simultaneously (using more than one thread until the pool is starved). Can you include some logging on start/end of operation and perhaps count the number of simultaneous calculations to check this?
If this is an issue you could include some logic whereby the CalculateAndNotify operation is queued up and new calculate operations cannot be executed until the previous has completed.
I have the following piece of code:
private Dictionary<object, object> items = new Dictionary<object, object>;
public IEnumerable<object> Keys
{
get
{
foreach (object key in items.Keys)
{
yield return key;
}
}
}
Is this thread-safe? If not do I have to put a lock around the loop or the yield return?
Here is what I mean:
Thread1 accesses the Keys property while Thread2 adds an item to the underlying dictionary. Is Thread1 affected by the add of Thread2?
What exactly do you mean by thread-safe?
You certainly shouldn't change the dictionary while you're iterating over it, whether in the same thread or not.
If the dictionary is being accessed in multiple threads in general, the caller should take out a lock (the same one covering all accesses) so that they can lock for the duration of iterating over the result.
EDIT: To respond to your edit, no it in no way corresponds to the lock code. There is no lock automatically taken out by an iterator block - and how would it know about syncRoot anyway?
Moreover, just locking the return of the IEnumerable<TKey> doesn't make it thread-safe either - because the lock only affects the period of time when it's returning the sequence, not the period during which it's being iterated over.
Check out this post on what happens behind the scenes with the yield keyword:
Behind the scenes of the C# yield keyword
In short - the compiler takes your yield keyword and generates an entire class in the IL to support the functionality. You can check out the page after the jump and check out the code that gets generated...and that code looks like it tracks thread id to keep things safe.
OK, I did some testing and got an interesting result.
It seems that it is more an issue of the enumerator of the underlying collection than the yield keyword. The enumerator (actually its MoveNext method) throws (if implemented correctly) an InvalidOperationException because the enumeration has changed. According to the MSDN documentation of the MoveNext method this is the expected behavior.
Because enumerating through a collection is usually not thread-safe a yield return is not either.
I believe it is, but I cannot find a reference that confirms it. Each time any thread calls foreach on an iterator, a new thread local* instance of the underlying IEnumerator should get created, so there should not be any "shared" memory state that two threads can conflict over...
Thread Local - In the sense that it's reference variable is scoped to a method stack frame on that thread
I believe yield implementation is thread-safe. Indeed, you can run that simple program at home and you will notice that the state of the listInt() method is correctly saved and restored for each thread without edge effect from other threads.
public class Test
{
public void Display(int index)
{
foreach (int i in listInt())
{
Console.WriteLine("Thread {0} says: {1}", index, i);
Thread.Sleep(1);
}
}
public IEnumerable<int> listInt()
{
for (int i = 0; i < 5; i++)
{
yield return i;
}
}
}
class MainApp
{
static void Main()
{
Test test = new Test();
for (int i = 0; i < 4; i++)
{
int x = i;
Thread t = new Thread(p => { test.Display(x); });
t.Start();
}
// Wait for user
Console.ReadKey();
}
}
class Program
{
static SomeCollection _sc = new SomeCollection();
static void Main(string[] args)
{
// Create one thread that adds entries and
// one thread that reads them
Thread t1 = new Thread(AddEntries);
Thread t2 = new Thread(EnumEntries);
t2.Start(_sc);
t1.Start(_sc);
}
static void AddEntries(object state)
{
SomeCollection sc = (SomeCollection)state;
for (int x = 0; x < 20; x++)
{
Trace.WriteLine("adding");
sc.Add(x);
Trace.WriteLine("added");
Thread.Sleep(x * 3);
}
}
static void EnumEntries(object state)
{
SomeCollection sc = (SomeCollection)state;
for (int x = 0; x < 10; x++)
{
Trace.WriteLine("Loop" + x);
foreach (int item in sc.AllValues)
{
Trace.Write(item + " ");
}
Thread.Sleep(30);
Trace.WriteLine("");
}
}
}
class SomeCollection
{
private List<int> _collection = new List<int>();
private object _sync = new object();
public void Add(int i)
{
lock(_sync)
{
_collection.Add(i);
}
}
public IEnumerable<int> AllValues
{
get
{
lock (_sync)
{
foreach (int i in _collection)
{
yield return i;
}
}
}
}
}