Вопрос

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

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

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

1. Решение Mutex:

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 - это быстрый способ создания новых объектов или .NET Platform выполняет хорошо в этом поле.

С наилучшими пожеланиями,

Фридрих

Это было полезно?

Решение

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

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

Другие советы

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

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) не могут возникать под спинком, чтобы они должны были быть сделаны под True Mutex.

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

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

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

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

Кроме того, рассмотрите возможность использования монитора (или оператора блокировки C # - то же самое), если вы обеспокоены весом. Замок / монитор выполняет лучше, чем Mutex. Тем не менее, он не виден за пределами вашего процесса (но затем вы не создаете названные Mutex, поэтому он выглядит так, как будто вам не нужно, чтобы он был виден за пределами вашего процесса).

Если вы будете использовать .NET 4, вы также можете посмотреть на новую структуру спинлок

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top