Войти в систему

Home
    - Создать дневник
    - Написать в дневник
       - Подробный режим

LJ.Rossia.org
    - Новости сайта
    - Общие настройки
    - Sitemap
    - Оплата
    - ljr-fif

Редактировать...
    - Настройки
    - Список друзей
    - Дневник
    - Картинки
    - Пароль
    - Вид дневника

Сообщества

Настроить S2

Помощь
    - Забыли пароль?
    - FAQ
    - Тех. поддержка



Пишет dibr ([info]dibr)
@ 2011-09-15 21:03:00


Previous Entry  Add to memories!  Tell a Friend!  Next Entry
синхронизация
     На работе пишем счётную программу, обсчитывающую нечто в двух нитях. Нити должны быть синхронизованы - одна не должна обгонять другую. Сделали так: ("псевдокод" на Си):
volatile int lock;

main()
{
 lock=0;
 create_thread(&thread1);
 create_thread(&thread2);
 {ждём и время от времени рисуем графики}
}


thread1()
{
while(1)
 {
  {что-то считаем}
  lock++;
  while(lock==1);
  lock=0;
 }
}

thread2()
{
while(1)
 {
  {что-то считаем}
  lock++;
  while(lock==1);
  lock=0;
 }
}

     Идея ясна: первая нить, досчитав, увеличивает lock, он становится равен 1, нить встаёт в цикл while и ждёт. Вторая нить, досчитав, увеличивает lock, он становится равен 2, нить сбрасывает lock в 0 и идёт на второй круг, первая нить, увидев 0, тоже идёт считать дальше. При желании это легко масштабируется на N нитей, заменой while(lock==1); на while(lock!=0 && lock!=N);. Да, я понимаю. что while(); грузит ядро на 100% - но разница в скорости работы нитей небольшая, да и ядро это всё равно простаивало бы, в ожидании соседней нити. Да, я знаю что "системными функциями было бы надёжнее", но нити крутятся очень быстро, вызывать относительно тяжеловесные системные функции как-то не хочется, такой вот spinlock побыстрее будет.
     Так вот. После нескольких десятков-сотен тысяч "оборотов" обе нити "зависают". Зависают в while(lock==1);. Почему - я так и не понял, volatile вроде не забыл, "гонок" я не вижу. Кто-нибудь может понять, на какие грабли мы тут наступили? Компилятор - какой-то не очень свежий borland C++ builder, какой точно - на работе посмотрю, навскидку не помню.
     Вопрос сейчас уже теоретический - блокировку переписали по другому, "так что работает", а поскольку задача счётная и "для себя", то и пофиг, лишь бы работало. Но чисто теоретически - какого фига? Что тут может быть, lock++ на самом деле неатомарный, или я гонки где-то не заметил?...


(Читать комментарии) - (Добавить комментарий)

Re: InterlockedIncrement вам нужен
[info]dibr@lj
2011-09-15 14:37 (ссылка)
Спасибо, буду знать :-)

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

(Ответить) (Уровень выше)


(Читать комментарии) -