zHz00 Untitled

понедельник, 22 июня 2015
23:53 Свиноматка
Хуже всего, если баг в программе то проявляется, то нет, по непонятному расписанию.

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

Если вы обнаружили подобный баг, то следует проверить следующее:
1) Что доступ к внешним устройствам есть только у одного потока. Если есть сомнения, следует сделать специальную функцию доступа к нему, которая будет работать через взаимоисключение (т.е. мьютекс, критическая секция и пр.). Весь доступ к устройству должен осуществляться через неё.
2) Что доступ к внутренним ресурсам (особенно, к памяти) размером больше ширины шины данных тоже сделан через взаимоисключения (см. примечание ниже).
3) И, наконец, что вы не применяете многопоточно библиотеки, которые для этого не предназначены. Если предназначены, обычно стоит пометка в документации -- thread-safe. Одна из таких библиотек, которая не предназначена -- VCL (C++ Builder, Delphi). Когда-то я не знал, что она не поддерживает многопоточность и менял, к примеру, надписи на кнопках из разных потоков. Это приводило к совершенно невообразимым глюкам.

Внимание. Примечание к п.2. На некоторых процессорах доступ к невыровненным данным выполняется в несколько тактов. Выровненными считаются данные, расположенные по адресам, равным n*ширина шины данных, где n -- целое неотрицательное число. Т.е. если ваша переменная размером 4 байта расположена по адресу 13, то её считывание на 32-битном процессоре может происходит следующим образом: процессор считывает байты 12-15, сохраняет во временный регистр, потом 16-19, сохраняет в другой регистр, сдвигает 12-15 влево на 8 бит, записывает старшие 24 бита в старшие 24 бита целевого регистра, потом сдгвигает 16-19 вправо на 24 бита, записывает младшие 8 бит в младшие 8 бит целевого регистра. Данный алгоритм является примером, фактическая реализация может быть иной. За это время потоки могли переключиться уже несколько раз. Будьте осторожны. Если же адрес переменной изначально был 12, то всё проходит в 1 такт.

@темы: Программирование, Очевидное-невероятное

URL
Жевал можжевельник. Hадувал лягушек. Размышлял о смысле ж...
Мадине 42, но выглядит она на все "тяжелые" 60....
Страна, говорю, своебразная, так что и духовность у них с...
И-нет еееееле пашет. Мало мне такого щастя дома, теперь е...
Ну вот и добрались мы до обычаев, благо смогу поделиться ...
С детства ненавидела дачу. А сейчас хочется взять тяпку и...

23.06.2015 в 09:52

23.06.2015 в 09:52
Один раз - не свинопас.
URL

24.06.2015 в 23:59

24.06.2015 в 23:59
Почему свиноматка?

размером больше ширины шины данных
И меньше тоже. A++ из двух потоков рано или поздно кончится плохо. Без блокировок можно использовать:
1. Переменные, локальные для потока.
2. Атомарные операции по отдельности (чтение, присвоение, проверка, Interlocked***), но не их комбинации.
Существует целая отрасль, в которой свои талмуды и профессионалы - lockless synchronization. Типичный приём - lockless однократная инициализация:



Т.е. создать, попробовать заменить NULL на него, но если там был не NULL, то кто-то успел раньше, уничтожить лишний object.

А ещё есть гейзенбаги, это которые исчезают, когда на них смотришь отладчиком (или логом) :)
URL

25.06.2015 в 18:16

25.06.2015 в 18:16
Свиноматка работает в несколько потоков же.

Что а плюс плюс закончится плохо -- да. Про это надо подправить. Спасибо.
URL

01.07.2015 в 22:48

01.07.2015 в 22:48
Меня всегда в глубине души ужасали рекомендации многих учебников "гарантировать", что процедура А запустится раньше, чем процедура Б в параллельном потоке. Поставить оператор паузы ненулевой длины во втором потоке перед Б! *снова содрогнулся*
URL

01.07.2015 в 23:50

01.07.2015 в 23:50
О, а дай-ка мне все эти учебники. Операторы паузы -- штука тяжёлая. В нашем ПО они регулярно применяются, но не для того, что ты пишешь, а для того, чтобы быть уверенным, что наши внешние устройства успеют получить и обработать отправленные им сообщения. Это всё равно плохо, но лучше чем то, что пишешь ты, т.к. устройства на контроллерах, а там жёсткое время выполнение.
URL

02.07.2015 в 09:59

02.07.2015 в 09:59
zHz00, дать, чтобы сжечь? Увы, почти все они - в электронном виде (я пират, йарр). Да и сам уже их не найду.

Ну, для гарантии (не 100%, но гарантия 100% - всегда ЛожьПП) получения и отправки сообщений с внешних устройств - в принципе, что ещё делать остаётся, управляющие сигналы а-ля мьютексы и проч. не всегда можно (или нужно) вводить в протокол. А с контроллерами всё действительно можно "подогнать" под эм... кадр.
Так что... что сказать-то... В общем, уверен, всё правильно делаете.
URL

02.07.2015 в 13:13

02.07.2015 в 13:13
Интересно, что люди пишут, т.к. мои сведения из этой области почёрпнуты из пары лекций специалиста в этой области, который работал с этим по работе (он у нас в институте читал курс связанный с программированием), бесед с несколькими братьями по разуму и личного опыта. Ну и документации. Что старый пират это понятно, но можешь хотя бы названия сказать. Или прислать в умейл.
URL

03.07.2015 в 00:23

03.07.2015 в 00:23
zHz00, обязательно поищу. Где-то точно валялись...
URL
Добавить комментарий

Расширенная форма

Подписаться на новые комментарии
Получать уведомления о новых комментариях на E-mail