Синхронизация

Тема в разделе "WASM.WIN32", создана пользователем Lex2029, 12 ноя 2007.

  1. Lex2029

    Lex2029 New Member

    Публикаций:
    0
    Регистрация:
    17 сен 2007
    Сообщения:
    199
    Всем привет.
    Как правильно синхронизировать 2 потока? Т.е. Есть переменная, 1 поток ее инкрементит, другой декрементит.
    Задача, чтоб ее значение не изменялось. Ну т.е. чтоб они по очереди работали.

    Почитал МСДН, нашел методы SuspendThread/ResumeThread НО:
    Если я делаю просто вот так:
    Код (Text):
    1. Thread1 PROC num:LPVOID
    2.     .while TRUE
    3.         inc     number
    4.         Invoke  ResumeThread,hThread2
    5.         Invoke  SuspendThread,hThread1
    6.     .endw
    7.     ret
    8. Thread1 ENDP
    9.  
    10. Thread2 PROC num:LPVOID
    11.     .while TRUE
    12.         dec     number
    13.         Invoke  ResumeThread,hThread1
    14.         Invoke  SuspendThread,hThread2
    15.     .endw
    16.     ret
    17. Thread2 ENDP
    То эти потоки выполняются по 1 разу и засыпают оба.

    Почитал МСДН :) Нашел то, что SuspendThread, инкрементит число сна, и поток не оживет, пока оно не станет равно 0. Так же узнал, что метод ResumeThread возвращает это число сна, до того как уменьшить его на 1.

    Переделал код:
    Код (Text):
    1. Thread1 PROC num:LPVOID
    2.     .while TRUE
    3.         inc     number
    4.         .while TRUE
    5.             Invoke  ResumeThread,hThread2
    6.             .break .if eax==1
    7.         .endw
    8.         Invoke  SuspendThread,hThread1
    9.     .endw
    10.     ret
    11. Thread1 ENDP
    12.  
    13. Thread2 PROC num:LPVOID
    14.     .while TRUE
    15.         dec number
    16.         .while TRUE
    17.             Invoke  ResumeThread,hThread1
    18.             .break .if eax==1
    19.         .endw
    20.         Invoke  SuspendThread,hThread2
    21.     .endw
    22.     ret
    23. Thread2 ENDP
    Все заработало. НО:
    Я вывожу каждую секунду в третем потоке, 2 числа, сколько отработали раз эти 2 потока. Вывожу на консоль. Так вот, когда эта консоль не активна, то каждый поток, отрабатывает ~по 10 000 раз, а как только я нажимаю на консоль и активирую ее, потоки начинают обрабатывать по 3-5 цикла в секунду :))) Вот такая вот штука.
    Помогите плиз!
     
  2. Noble Ghost

    Noble Ghost New Member

    Публикаций:
    0
    Регистрация:
    28 апр 2004
    Сообщения:
    204
    Адрес:
    Russia
    !google critical sections winapi

    upd: пардон, невнимательно прочитал )
     
  3. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    По очереди? Можно на критических секциях, можно на ядерных объектах (мьютексы, семафоры, события), можно придумать что-то своё.
     
  4. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    InterlokedXXXXX функции.
     
  5. Lex2029

    Lex2029 New Member

    Публикаций:
    0
    Регистрация:
    17 сен 2007
    Сообщения:
    199
    Спасибо, но скажите еще что-нибудь про мои примеры. Почему так происходит?

    И еще, как сделать что-то типа wait, который будет просыпаться по команде? Я нашел CreateMutex и WaitForSingleObject, но что это так и не понял... т.к. этот Wait нифига не ждет.
     
  6. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Смотри описание WaitForSingleObject - какие объекты он может "ждать" и выбирай любой из них.

    По мьютексам - можно сделать следующее:
    * создание мьютекса в основном потоке, bInitialOwner = false
    * создание потоков с передачей им хэндла мьютекса либо просто использовать глобальную переменную

    * в потоке:
    ** попытка захватить мьютекс через WaitForSingleObject(g_hMutex, INFINITE). Т.к. он изначально создан не захваченным, то первый поток захватит его.
    ** изменение переменной
    ** освобождение мьютекса с помощью ReleaseMutex
    ** Sleep(n), чтобы гарантированно отдать время другому потоку
    ** переход обратно к ожиданию, если у тебя потоки в цикле работают с переменной

    * во втором потоке происходит то же самое: попытка захвата и ожидание, если другой поток уже захватил мьютекс; работа с переменной; освобождение и т.п.
     
  7. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    Lex2029
    По-моему стоит прочитать Рихтера, если тебя интересуют эти вопросы.
     
  8. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    в данном случае имхо крит. секции - это то что надо
     
  9. Lex2029

    Lex2029 New Member

    Публикаций:
    0
    Регистрация:
    17 сен 2007
    Сообщения:
    199
    Всем спасибо! Разобрался, и Рихтер тоже супер помог!