Вопрос об интервью на поточной обработке.NET

Вы могли описать два метода синхронизации многопоточного доступа для записи, выполненного на участнике класса?

Мог любой помогать мне, что, это означало делать и что является правильным ответом.

7
задан Hassan Syed 22 January 2010 в 13:17
поделиться

3 ответа

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

public class Number {
    private int a = 0;
    public void Add(int b) {
        a += b;
    }
}

, когда вы построите его, вы получаете следующий код IL:

IL_0000:  nop
IL_0001:  ldarg.0
IL_0002:  dup
// Pushes the value of the private variable 'a' onto the stack
IL_0003:  ldfld      int32 Simple.Number::a
// Pushes the value of the argument 'b' onto the stack
IL_0008:  ldarg.1
// Adds the top two values of the stack together
IL_0009:  add
// Sets 'a' to the value on top of the stack
IL_000a:  stfld      int32 Simple.Number::a
IL_000f:  ret

Теперь, скажем, у вас есть объект , и два потока вызова его Добавить метод Как это:

number.Add(2); // Thread 1
number.Add(3); // Thread 2

Если вы хотите, чтобы результат был 5 (0 + 2 + 3), есть проблема. Вы не знаете, когда эти потоки будут выполнять свои инструкции. Обе нити могут выполняться IL_0003 (нажав ноль на стек) перед выполнением IL_000A (фактически изменение переменной элемента), и вы получаете это:

a = 0 + 2; // Thread 1
a = 0 + 3; // Thread 2

Последняя поток для окончания победы «И в конце процесса A - 2 или 3 вместо 5.

, поэтому вы должны убедиться, что один полный набор инструкций заканчивается до другого набора. Для этого вы можете:

1) блокировать доступ к элементу класса, когда он написан, используя один из многих примитивов синхронизации .NET (вроде блокировки , Mutex , READERWRITERLOCKSSLIM и т. Д.) Так что только один поток может работать на нем за раз.

2) Нажмите «Записать операции в очередь» и обрабатывайте эту очередь одним потоком. Когда торарин указывает, вы все еще должны синхронизировать доступ к очереди , если это не безопасно, но оно того стоит для сложных операций записи.

Есть и другие методы. Некоторые (вроде заблокированы ) ограничены определенными типами данных, и даже больше (например, те, которые обсуждаются в , не блокирующих синхронизацию , а часть 4 резьба Джозефа Альбахари в C # ), хотя они более сложны: подходите к ним с осторожностью.

13
ответ дан 6 December 2019 в 07:06
поделиться

Есть несколько способов, несколько из которых упоминаются ранее.

  1. ReaderWriterLockSlim - мой предпочтительный метод. Это дает вам тип блокировки базы данных, и позволяет обновлять (хотя синтаксис для этого неверна в MSDN в прошлый раз, когда я смотрел, и очень неочевидно)
  2. заблокированные операторы. Вы относитесь к чтению как писать и просто предотвратить доступ к переменной
  3. заблокированными операциями. Это выполняет операции по типу значения на атомном шаге. Это можно использовать для блокировки Free Threading (действительно не рекомендую это)
  4. Mutexes и Semaphores (не использовали их)
  5. Заявления монитора (это, по сути, как работает ключевое слово блокировки)

, пока я не буду Я хочу определить другие ответы, я бы не доверял ничего, что не использует одну из этих методов. Мои извинения, если я забыл.

0
ответ дан 6 December 2019 в 07:06
поделиться

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

Предлагаю, что они означают, что они имеют в виду использование блокировки (или Synclock в VB.NET) против с использованием монитора .

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

Существует приличный на странице MSDN на эту тему .

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

В качестве управлений и демонстрация проблемы, попробуйте написать приложение, которое начинается 5 одновременных потоков, увеличивая общий счетчик в миллион раз на поток. Предназначенный конечный результат счетчика составит 5 миллионов, но это (вероятно) не то, что вы получите с :)

Редактировать: сделал быструю реализацию себя ( скачать ). Образец вывода:

Unsynchronized counter demo:
expected counter = 5000000
actual counter   = 4901600
Time taken (ms)  = 67

Synchronized counter demo:
expected counter = 5000000
actual counter   = 5000000
Time taken (ms)  = 287
12
ответ дан 6 December 2019 в 07:06
поделиться
Другие вопросы по тегам:

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