Что гарантирует поток видит последнее значение при передаче данных между двумя потоками? - PullRequest
0 голосов
/ 20 ноября 2018

Я использую собственную библиотеку через вызовы PInvoke, которая возвращает байт * и хочу убедиться, что в сценарии производитель / потребитель поток потока получает последние данные.

У меня есть очень надуманный пример, чтобы попытаться проиллюстрировать то, что я спрашиваю.Я знаю о «горячей петле» в Consumer (это всего лишь пример, реальный код намного больше и его невозможно вставить сюда).

public unsafe class ThreadExample {
  class PInvokeResult {
    public Byte* Data;
    public Int32 Length;
  }

  // Shared Objects Used For Synchronization
  Object SyncRoot = new Object();
  Queue<PInvokeResult> WorkQueue = new Queue<PInvokeResult>();

  // Producer Thread
  void Producer() {
    while (true) {
      PInvokeResult workItem;
      workItem = new PInvokeResult();
      workItem.Data = PInvokeNativeLongRunningCall(out workItem.Length);

      lock (SyncRoot) {
        WorkQueue.Enqueue(workItem);
      }
    }
  }

  // Consume Thread
  void Consumer() {
    while (true) {
      bool workAvailable = false;
      PInvokeResult workItem = null;

      lock (SyncRoot) {
        if (WorkQueue.Count > 0) {
          workItem = WorkQueue.Dequeue();
          workAvailable = true;
        }
      }

      if (workAvailable) {
        ProcessWorkItem(workItem);
        PInvokeReturnPointerBuffer(workItem.Data);
      }
    }
  }
}

Блокировка здесьдостаточно, чтобы убедиться, что данные, считываемые с указателя Byte* на PInvokeResult, никогда не указывают на «устаревшие» данные для потребителя?

В данном случае я имею в виду устаревшие данные:

  1. Один конкретный буфер байта * возвращается из вызова PInvokeNativeLongRunningCall.
  2. Буфер передаетсяот производителя до потребителя это использует блокировку SyncRoot, чтобы убедиться, что доступ к очереди безопасен.
  3. Потребитель выполняет некоторую работу над элементом и затем возвращает его в собственный код через PInvokeReturnPointerBuffer
  4. Затем буфер перерабатывается и используется повторно на собственной стороне, а данные в буфере сначала устанавливаются на все нули, а затем записываются снова.
  5. Затем цикл начинается с 1.

Когда буфер второй раз приходит к потребителю, как я могу быть уверен, что данные, которые он видит, являются последними новыми данными, записанными вызовом PInvoke?

Этот вопрос чисто с точки зрения C #, я знаю, что нативный код - хороший и надежный, это хорошо используемая библиотека.

Это даже то, что язык должен учитывать, или этоКолорадополностью обрабатывается самим процессором?

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