Блокировка чтения / записи - PullRequest
1 голос
/ 08 июня 2009

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

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

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

Ответы [ 10 ]

7 голосов
/ 08 июня 2009

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

3 голосов
/ 08 июня 2009

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

Затем протестируйте его на машинах с 64-разрядными, более быстрыми процессорами, большим количеством процессоров и т. Д.

И, как говорит @ onebyone.livejournal.com, используйте машину с некогерентными кешами памяти; хотя, согласно статье NUMA в Википедии , это может быть трудно найти.

Конечно, использование кода на как можно большем количестве разных машин не повредит, а также является хорошим способом выявления проблем.

3 голосов
/ 08 июня 2009

Полагаю, вы можете начать с просмотра тестов, включенных в устоявшийся код. Например, реализация GNU libc (nptl) для pthreads включает в себя блокировки чтения-записи и некоторые тесты.

$ ls nptl/tst-rwlock*
nptl/tst-rwlock1.c
nptl/tst-rwlock10.c
nptl/tst-rwlock11.c
nptl/tst-rwlock12.c
nptl/tst-rwlock13.c
nptl/tst-rwlock14.c
nptl/tst-rwlock2.c
nptl/tst-rwlock3.c
nptl/tst-rwlock4.c
nptl/tst-rwlock5.c
nptl/tst-rwlock6.c
nptl/tst-rwlock7.c
nptl/tst-rwlock8.c
nptl/tst-rwlock9.c
1 голос
/ 08 июня 2009

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

Тестирование и построение примитивов синхронизации могут быть сложными и не интуитивными.

Руководство по использованию boost :: shared_mutex весьма разумно, если вы работаете на платформе Win32, я бы посоветовал вам использовать Slim Reader Writer Locks , если это возможно, потому что они надежные и быстрые.

Хотя сегодня это не поможет производственному продукту, в Visual Studio 2010 Beta 1 мы добавили класс reader_writer , который, хотя и не является кроссплатформенным, будет частью перенаправления VS2010.

0 голосов
/ 08 июня 2009

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

0 голосов
/ 08 июня 2009

IBM имеет инструмент анализа для выявления проблем с многопоточностью в Java . Возможно, есть что-то подобное для C ++?

0 голосов
/ 08 июня 2009

Если вы вообще можете использовать Boost в своем рабочем коде, вам следует использовать класс shared_mutex, который реализует блокировку чтения / записи.

Даже если он не на 100% соответствует вашим потребностям, вы должны использовать идеи в коде для своего кода, и, если в коде Boost есть тесты для shared_mutex (я не проверял), вам следует добавьте их в свои тесты.

0 голосов
/ 08 июня 2009

Используйте ASSERT / assert часто, чтобы проверить все ваши предположения и проверить предварительные и последующие условия.

0 голосов
/ 08 июня 2009

Запустите два потока, которые оба делают это

  long long int j = 0;
  long long int oldJ = 0;
  while (true)
  {
      for (long long int i = 0; i <= 100000; ++i) 
       // try and make it 64 bits to be sure its non-atomics :)
      {       
          oldJ = j;      
          YourRead(j) // read in j
          assert(j == (oldJ + 1));
          SleepSomeRandomPeriod(  );
          YourWrite(i)
          SleepSomeRandomPeriod(  );
      }
  }
0 голосов
/ 08 июня 2009

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

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