C # Многопоточность синхронизации - PullRequest
0 голосов
/ 04 апреля 2011

Я делаю одну программу, которая нуждается в многопоточной синхронизации.Вот мои методы:

    private void RunSimulation()
    {
        int sideSize = (int)Math.Ceiling((double)_simulationField.GetLength(0) / (double)MAX_SECTOR_SIZE);
        int threadsCount = sideSize * sideSize;
        sync = new bool[threadsCount + 1];
        for (int i = 0; i < sync.Length; i++)
        {
            sync[i] = false;
        }
            for (int sector = 0; sector <= threadsCount; sector++)
            {
                Thread sectorThread = new Thread(DoSector);
                sectorThread.IsBackground = true;
                sectorThread.Start(sector);
            }
    }

И:

    private void DoSector(object obj)
    {
        int sector = (int)obj;
        Library.Pair sectorPosition = GetSectorPosition(sector);
        while (true)
        {

            for (int i = sectorPosition.X; i < sectorPosition.X + MAX_SECTOR_SIZE && i < _simulationField.GetLength(0); i++)
            {
                for (int j = sectorPosition.Y; j < sectorPosition.Y + MAX_SECTOR_SIZE && j < _simulationField.GetLength(1); j++)
                {
                    if (_simulationField[i, j] != null)
                    {
                        MoveCreature(_simulationField[i, j], i, j);
                    }
                }
            }
            sync[sector] = true;
            while (sync.Contains(false) && sector != sync.Length)
            {
                Thread.Sleep(10);
            }
            if (sector == sync.Length)
            {
                for (int i = 0; i < sync.Length; i++)
                {
                    sync[i] = true;
                }
            }
            Thread.Sleep(500);
        }
    }

Итак, вы можете видеть, что я использую массив для синхронизации.Но я брожу, это хороший способ сделать это?Здесь операция sync.Contains имеет сложность O (n) и находится в цикле ... Есть ли лучший способ выполнить синхронизацию?

Ответы [ 2 ]

2 голосов
/ 04 апреля 2011

Я думаю, что вы хотите использовать Барьер здесь.Это объект синхронизации, позволяющий выполнять потоки поэтапно.Все потоки должны завершить свои вычисления в одну фазу, прежде чем им позволят выполнить следующую.Это как раз то, что вам нужно.

0 голосов
/ 04 апреля 2011

Использование массива для синхронизации не является потокобезопасным, но только "sync.Contains (false)".

Что если два потока запущены sync.Contains (false) одновременно и оба возвращаются false?

Кроме того, я вижу, что ваш ThreadCount является квадратом sideSize. Создание большого количества потоков очень неэффективно. чем больше у вас потоков, тем больше у вас переключений контекста. Переключение контекста составляет около 8000 тактов. Кроме того, создание потока стоит около 100 000 тактов, и каждый поток должен иметь свой собственный стек, который по умолчанию составляет около 4 МБ.

Вам нужно столько же потоков, сколько ядер, и каждый поток извлекает из очереди и обрабатывает свою работу.

Возможно, вам лучше использовать пул потоков, но я также вижу, что ваши потоки через некоторое время (правда), что означает, что они никогда не заканчиваются. Пул потоков не предназначен для длинных потоков.

В целом, я думаю, что ваш дизайн нуждается в некоторой работе. Поскольку вы, кажется, учитесь, я бы порекомендовал проект, который позволяет использовать пул потоков вместо циклов while (true).

Кто-то другой может дать вам «имя» для известного шаблона дизайна, который будет работать для вас, но я не знаю названия шаблонов дизайна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...