问题
I'm working on my project about Bakery Algorithm but i don't have any demo of that Algorithm in C# . Because of that situation i've converted some java code that i found on Wikipedia . But Anyway , it doesn't seem to work !
Updated : Here's my full-working code ( old code include in "//" comment )
namespace BakeryAlgorithm
{
class Program
{
static int threads = 10;
static string x = "";
static int count = 0;
static int[] ticket = new int[threads];
static bool[] entering = new bool[threads];
public static void doLock(int pid)
{
entering[pid] = true;
int max = 0;
for (int i = 0; i < threads; i++)
{
if (ticket[i] > ticket[max]) { max = i; }
}
ticket[pid] = 1+max;
entering[pid] = false;
for (int i = 0; i < threads; ++i)
{
if (i != pid)
{
while (entering[i])
{
Thread.Yield();
}
while (ticket[i] != 0 && (ticket[pid] > ticket[i] ||
(ticket[pid] == ticket[i] && pid > i)))
{
Thread.Yield();
}
}
}
if (x == "C" || x == "c")
Console.WriteLine("[System] PID " + pid.ToString() + " get into critical section");
}
public static void unlock(int pid)
{
ticket[pid] = 0;
count++;
Console.WriteLine("[Thread] PID " + pid.ToString() + " process completed");
}
public static void arrayInit()
{
for (int i = 0; i < threads; i++)
{
ticket[i] = 0;
entering[i] = false;
}
}
public static void simThread(int i)
{
doLock(i);
if (x == "C" || x=="c")
Console.WriteLine("[Thread] PID " + i.ToString() + " begin to process...");
Random rand = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
int a = rand.Next(5,10);
int b = rand.Next(1,5);
int c = rand.Next(1,4);
double d = 0;
string o="";
if (c == 1)
{
d = a + b;
o=" + ";
}
else if (c == 2)
{
d = a * b;
o=" * ";
}
else if (c == 3)
{
d = a / b;
o=" / ";
}
else
{
d = a - b;
o=" - ";
}
if (x == "C" || x == "c")
Console.WriteLine("Result of PID " +i.ToString() +" : " + a.ToString() + o + b.ToString() + "=" + d.ToString());
unlock(i);
}
[STAThread]
static void Main(string[] args)
{
arrayInit();
string choice="C";
while (choice == "C" || x == "c")
{
Console.WriteLine("Do you want to see progress log ? (C=Yes,K=No) : ");
x = Console.ReadLine();
if (x == "")
x = "C";
Console.Clear();
Console.WriteLine("----------------------------------");
Console.WriteLine("Bakery Algorithm in C#");
Console.WriteLine("Number of threads : " + threads.ToString());
Console.WriteLine("Progress Log");
Console.WriteLine("----------------------------------");
Thread[] threadArray = new Thread[threads];
for (int i = 0; i < 10; i++)
{
//New code that solved my problem
int copy = i;
threadArray[i] = new Thread(() => simThread(copy));
//My old code that cause my problem
//threadArray[i] = new Thread(() => simThread(i));
if (x == "C" || x == "c")
Console.WriteLine("[System] PID " + i.ToString() + " has been created");
threadArray[i].Start();
Thread.Sleep(20);
}
Console.ReadLine();
Console.WriteLine("----------------------------------");
Console.WriteLine("Process completed " + count.ToString() + " threads !");
count = 0;
Console.WriteLine("----------------------------------");
Console.WriteLine("Do you want to restart the algorithm (C=Yes,K=No)");
choice = Console.ReadLine();
if (choice == "")
choice = "C";
}
}
}
}
回答1:
This is the problem:
threadArray[i] = new Thread(() => simThread(i));
You're capturing i
here - the single variable which will be updated over the course of the loop, and end up with a value of threads
.
If the thread only actually executes the body of the lambda expression after the loop is completed, that value will basically be inappropriate... and even if it doesn't, you could easily have multiple threads using the same value of i
.
You basically want a separate variable for each iteration of the loop, e.g.
for (int i = 0; i < threads; i++)
{
int copy = i;
threadArray[i] = new Thread(() => simThread(copy));
Console.WriteLine("[He Thong] PID " + i.ToString() + " duoc khoi tao");
threadArray[i].Start();
}
That way each iteration of the loop captures a separate variable which has the value of i
for that iteration, but which isn't then changed.
That's the smallest change between your current code and working code - but personally I'd be looking to make larger changes to use the TPL more heavily, have separate self-contained objects instead of parallel arrays etc.
来源:https://stackoverflow.com/questions/29745205/index-out-of-bounds-when-create-new-thread-with-parameters