Синхронизация переменных в многопоточном консольном приложении
Я пытаюсь писать приложение с использованием потоков, но переменная count не обновляется в рамках всех действующих потоков, ниже после кода приведён пример.
А так же random застревает на одном значении.
Я подозреваю что я что-то не записал или выбрал не очень удачный аналог рандома.
public class Calculate
{
static object locker = new object();
static int count = 0;
public static void Strike()
{
int[] bufer = new int[15];
lock (locker)
{
Random rnd = new Random();
for (int j = 1; j < bufer.Length - 1; j++)
{
bufer[j] = rnd.Next(0, 2);
}
}
Console.Write(++count+") "+bufer.ToString());
}
public static double Final
{
get
{
Thread thread1 = new Thread(Strike);
thread1.Start();
Thread thread2 = new Thread(Strike);
thread2.Start();
Thread thread3 = new Thread(Strike);
thread3.Start();
Thread thread4 = new Thread(Strike);
thread4.Start();
return 99;//не обращайте внимание
}
}
}
При запуске оно выводит 4 одинаковые записи. А хотелось бы чтобы нумерация шла как надо и числа 0 и 1 генерировались случайным образом.
"Как есть"
1) 1 1 1 0 1 0 1 0 1 0 1 1 1 0 1 246
1) 1 1 1 0 1 0 1 0 1 0 1 1 1 0 1 246
1) 1 1 1 0 1 0 1 0 1 0 1 1 1 0 1 246
1) 1 1 1 0 1 0 1 0 1 0 1 1 1 0 1 246
"Как должно быть"
1) 1 1 1 0 1 0 1 0 1 0 1 1 1 0 1 246
2) 1 0 1 1 0 1 1 0 1 0 1 0 1 0 1 334
3) 1 1 0 1 1 1 1 0 1 1 0 1 0 1 1 228
4) 1 1 0 1 0 0 1 0 1 1 0 1 0 1 1 288
Ответы (1 шт):
Interlocked.Increment - гарантирует, что несколько потоков не обновляют одну переменную параллельно.
Также, раз Вы только начали использовать потоки, рекомендую обратить внимание на Task, лично мне очень помогло. Вот простейший пример
UPD2:
public class Calculate
{
private static int[][] bufer = new int[4][];
private static async Task Strike(int number)
{
bufer[number] = new int[15];
Random rnd = new Random();
for (int j = 0; j < bufer.Length; j++)
{
bufer[number][j] = rnd.Next(0, 2);
}
}
public static double Final
{
get
{
Task[] taskArray = new Task[4];
for (int i = 0; i < taskArray.Length; i++)
{
int index = i; // Поверь, так лучше.
// Потоки стартуют с небольшим запаздыванием, и если использовать i,
// то рано или поздно выйдешь за пределы массива
taskArray[index] = Task.Run(() => Strike(index));
}
Task.WaitAll(taskArray);
for (int i = 0; i < taskArray.Length; i++)
{
Console.Write(i + ") " + bufer[i].ToString());
}
return 99;//не обращаю внимания
}
}
}