以下は、単純な同時実行スロットルと関連テストです。なぜなら、指定されているよりも並行性を監視するよりも頻繁には動作しませんが、なぜそれほどわかりませんか?同時実行スロットル
doWorkState.Throttle.Enter();
try
{
doWorkState.MaxRegister.Increment();
Thread.Sleep(10);
}
finally
{
doWorkState.MaxRegister.Decrement();
doWorkState.Throttle.Exit();
}
MaxRegister.Increment
とMaxRegister.Decrement
が伴う:
[TestFixture]
public class ConcurrencyThrottleTests
{
[Test]
public void ThrottleTest()
{
var throttle = new ConcurrencyThrottle(2);
var maxReg = new MaxRegister();
var threadPool = new SmartThreadPool();
var state = new DoWorkState {Throttle = throttle, MaxRegister = maxReg};
var workItemResults = new List<IWaitableResult>();
for (int i = 0; i < 1000; i++)
workItemResults.Add(threadPool.QueueWorkItem(DoWork, state));
SmartThreadPool.WaitAll(workItemResults.ToArray());
Assert.IsTrue(maxReg.MaxValue <= 2);
}
public void DoWork(object state)
{
var doWorkState = (DoWorkState)state;
doWorkState.Throttle.Enter();
try
{
doWorkState.MaxRegister.Increment();
Thread.Sleep(10);
}
finally
{
doWorkState.MaxRegister.Decrement();
doWorkState.Throttle.Exit();
}
}
public class DoWorkState
{
public IConcurrencyThrottle Throttle { get; set; }
public MaxRegister MaxRegister { get; set; }
}
public class ConcurrencyThrottle : IConcurrencyThrottle
{
private readonly int _max;
private readonly object _lock = new object();
private readonly MaxRegister _register = new MaxRegister();
public ConcurrencyThrottle(int max)
{
_max = max;
}
public void Exit()
{
lock (_lock)
{
_register.Decrement();
Monitor.Pulse(_lock);
}
}
public void Enter()
{
lock (_lock)
{
while (_register.CurrentValue == _max)
Monitor.Wait(_lock);
_register.Increment();
}
}
}
public class MaxRegister
{
public int MaxValue { get; private set; }
public int CurrentValue { get; private set; }
public void Increment()
{
MaxValue = Math.Max(++CurrentValue, MaxValue);
}
public void Decrement()
{
CurrentValue--;
}
}
}
あなたの共有MaxRegisterクラスはスレッドセーフではありません...それは問題ではないと確信していますか? –
私はスロットルのロックセクションから呼び出すだけなので、それは問題ではないと思います。 –
しかし、あなたはスロットルで並行性= 2を持っているので、DoWorkのtryブロックに2つのスレッドが同時に存在する可能性があります。 (私は、ConcurrencyThrottleからではなく、DoWorkからのMaxRegister.Increment/Decrementへの呼び出しを参照していました) –