我希望有一个静态(全局)计算器池,这些计算器将由许多不同的线程访问。 经过一番研究后,我发现Arrays的元素是线程安全的。 我认为将不同的计算器(在运行时之前的数量未知)存储在静态数组(calculator []计算器)中是个好主意。
如何确保一个计算器只使用一个计算器? 我阅读了整个msdn文档,所以不要发布"只有"请链接。
我还考虑过一个bool阵列"锁定"但我无法找到实现此线程安全的方法。
到目前为止我的代码:
internal static class Calculators
{
private static Semaphore pool;
private static bool[] locked;
private static calcs[] neuralNetworks;
private static Thread[] threads;
internal static Calculators(){
int number = Globals.Number;
pool = new Semaphore(number, number);
locked = new bool[number];
calcs = new calcs[number];
threads = new Thread[number];
for (int index = 0; index < number; index++)
{
// all neuralNetworks are unlocked by default
locked[index] = false;
// generate one network per "countThreads"
calcs[index] = Globals.CalcObj;
// generate one thread for each neural network
threads[index] = new Thread(new ThreadStart());
}
}
private int WhichCalculators()
{
int index;
for (index = 0; index < countThreads; index++)
{
if (locked[index] == false)
{
locked[index] = true;
return index;
}
}
throw new Exception("Calculators was called, but there weren't any networks unused");
}
}
代码更新: 如果我打电话给#34; WhichCalculator()&#34;那么它应该工作吗?在这个方法?
private static void doStuff()
{
pool.WaitOne();
Monitor.Enter(thisLock);
try
{
int whichCalculator = WhichCalculator();
locked[whichCalculator] = true;
lock (calculators[whichCalculator])
{
Monitor.Exit(thisLock);
// do stuff
locked[whichCalculator] = false;
}
}
catch
{
Monitor.Exit(thisLock);
}
//Calculate();
pool.Release();
}
问题2: 我是否正确地假设,静态构造函数将在第一次(或之前)第一次执行此类或其任何成员时执行?
答案 0 :(得分:1)
是的,你必须使用锁。但是数组和计算器的每个实例都会再次出现。
如果你可以在启动代码的多线程部分之前填充数组,那么你也不需要锁定数组(只有读取不会因静态内容而产生问题),但是通过调整数组大小,你需要锁定每个数组。访问它(写作和阅读)。 所以你的代码看起来像这样:
Calculator calc = null;
lock(calculators)
{
calc = calculators[0];
}
lock(calc)
{
// ... do stuff
}
这样,数组不再被锁定,然后需要锁定计算器本身。
答案 1 :(得分:0)
你可以lock你的阵列。这将确保每个数组操作都是线程安全的。
要确保每个对象一次只使用一次,您可以向其添加标记,例如calculator.InUse
。如果您无法在课程中添加标记,则可以使用extension method。