先贴下代码
_Datas.ParallelForEach(arg_nDataStartIndex, arg_nDataCount, (data) => { dMax = dMax.Max(data.HighPrice); dMin = dMin.Min(data.LowPrice); });Max,Min的实现如下:
public static T Min(this IComparable arg_oThis, T arg_oOther) { return arg_oThis.CompareTo(arg_oOther) < 0 ? (T)arg_oThis : arg_oOther; } public static T Max (this IComparable arg_oThis, T arg_oOther) { return arg_oThis.CompareTo(arg_oOther) > 0 ? (T)arg_oThis : arg_oOther; }
代码很简洁,但是其实问题很大。得到的最大值有时候(一般10次会有2次)是一个比较大的值,但不是最大值。 最小值得到是比较小的值
主要问题是 dMax = dMax.Max(data.HighPrice) 不是同步的。
但是又不想用lock
想用 Interlocked.CompareExchange 这个函数达到取极值的效果
代码如下:
_Datas.ParallelForEach(arg_nDataStartIndex, arg_nDataCount, (data) => { double m0, m1; do { m0 = dMin; m1 = dMin; if (data.LowPrice >= m0) break; m1 = data.LowPrice; } while (m0 != Interlocked.CompareExchange(ref dMin, m1, m0)); do { m0 = dMax; m1 = data.HighPrice; if (m1 <= m0) break; } while (m0 != Interlocked.CompareExchange(ref dMax, m1, m0)); //dMax = dMax.Max(data.HighPrice); //dMin = dMin.Min(data.LowPrice); });
其中的while用于检测是否发生过冲突,如果是则再次比较
经过检测4核上1000个数据发生了10次冲突