взаимная блокировка по сравнению со взаимным исключением, проблемами увеличения масштаба

Я сталкиваюсь с проблемой, что у меня есть C# объект (.NET), общий для некоторые потоки. Поток мог бы заменить объект другим. Потоки, просыпаются от соединения TCP/IP с помощью Асинхронной платформы.

Последовательность:

Потоки (ожидающий соединения)-> Асинхронный Обратный вызов-> Делает что-то ориентированное на многопотоковое исполнение-> Получает доступ к общему объекту->, Делают что-то ориентированное на многопотоковое исполнение.

1. Взаимное исключение решения:

Object sharedObject = new Object();
Mutex objectMutex = new Mutex();

void threadCallback()
{
  Object newObject = new Object();

  // some processing

  objectMutex.lock();
  // do exchange sharedObject with newObject if needed
  // very little processing here
  objectMutex.unlock();

  // some processing
}

2. Взаимная блокировка решения

Object sharedObject = new Object();
int usingSharedObject = 0;

void threadCallback()
{
  Object newObject = new Object();

  // some processing

  // poll until we lock
  while(1 == Interlocked.Exchange(ref usingSharedObject , 1))
  {
    // do exchange sharedObject with newObject if needed
    // very little processing here
    Interlocked.Exchange(ref usingSharedObject , 0); // free lock
  }

  // some processing
}

Что быстрее и увеличивается лучше?

Я ожидаю второе решение быть быстрее, пока нет ко многим потокам, опрашивающим одновременно. Второе решение могло бы даже спать случайное время так, чтобы опрос не съедал времени обработки. Первое решение смотрит инструмент для очистки мне, если я действительно должен обработать много соединений TCP/IP. Так как я делаю очень мало обработки в заблокированном разделе относительно обработки TCP/IP, там будут какие-либо увеличивать-масштаб-проблемы?

Как насчет создания объекта в начале threadCallback () функция.

В моем образовании C++ я всегда использовал пулы памяти в такой ситуации, так как я должен использовать безопасную.NET, там быстрый способ создать новые Объекты или делает платформу.NET, работают хорошо в этом поле.

С уважением,

Friedrich

5
задан Friedrich 3 February 2010 в 16:18
поделиться

5 ответов

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

Подход Mutex намного легче понять, и у меня не было проблем с производительностью.

2
ответ дан 13 December 2019 в 19:27
поделиться

Если вы используете .Net 4, вы также можете взглянуть на новую структуру SpinLock

0
ответ дан 13 December 2019 в 19:27
поделиться

Ваша разблокированная операция некорректна. Обычно спин-блокировка выглядит следующим образом:

int sharedLock = 0;

void callback()
{

do {
 int existingState = Interlocked.CompareExchange(ref sharedLock, 1, 0);
 if (0 == existingState) {
  break;
 }
} while (true);

try
{
 // operate on the shared state
}
finally
{
 int existingState = Interlocked.Exchange(ref sharedLock, 0);
 Debug.Assert (1 == existingState);
}

}

Так как причина использования одного против другого, то в первую очередь это зависит от типа операций, выполняемых во время удержания блокировки. Очень короткие операции (короткие арифметические сложения/субстракции, простые смены флагов состояния и т.д.) лучше подходят для спин-блока. Тяжелые операции (распределения, доступ к IO) не могут происходить под спинблоком, поэтому они должны выполняться под истинным мьютексом.

5
ответ дан 13 December 2019 в 19:27
поделиться

На первый взгляд кажется, что два ваших примера могут не быть эквивалентными. Мне кажется, что ваше решение для опроса, использующее Interlocked.Exchange () , попадет в цикл обработки, в то время как что-то еще потребовало «самодельный семафор» и пропустит замену sharedObject и newObject , если заявлен самодельный семафор. (Если я чего-то не понимаю, что вполне возможно).

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

Win32 добавил объект-мьютекс со счетчиком вращений, чтобы получить лучшее из того, что вы здесь пытаетесь сделать (я думаю). Однако, насколько мне известно, он еще не был представлен в платформе .NET.

3
ответ дан 13 December 2019 в 19:27
поделиться

Я бы пошел по маршруту Mutex (), пока вы не убедитесь, что вам нужно что-то более экзотическое.

Также рассмотрите возможность использования Monitor (или оператора блокировки в C # - то же самое), если вас беспокоит вес. Блокировка / монитор работает лучше, чем мьютекс. Однако он не виден за пределами вашего процесса (но тогда вы не создаете именованный мьютекс, поэтому похоже, что вам не нужно, чтобы он был виден вне вашего процесса).

1
ответ дан 13 December 2019 в 19:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: