Author Topic: потоки одномоментно проверяют глобальный флаг?  (Read 3712 times)

0 Members and 2 Guests are viewing this topic.

i0

  • Оплот сообщества
  • ****
  • Posts: 353
  • CMann 4.13.014 final, ie, presto, win7 x86, x64
    • View Profile
2 потока включаемые в процессе работы скрипта
При начале действий в одном из них ставится глобальный флаг занятости, другой поток должен ждать снятия флага.

Но иногда в начале работы этого не происходит, и оба потока начинают действия одновременно (позже всё устаканивается).
Считал, прочтя описание, что это невозможно. Как избежать такой ситуации?

[spoiler=код]
Code: (clickermann) [Select]
thread(t1, 0)
   if ( $bBusy )
      logwrite( "t1: жду" )
      wait( 1 )
   else
      $bBusy = 1
      logwrite( "t1: работа 5 c..." )
      wait( 5 )
      logwrite( "t1: ... завершена" )
      $bBusy = 0
      wait( 2 )
   end_if
end_thread

thread(t2, 0)
   if ( $bBusy )
      logwrite( "   t2: жду" )
      wait( 1 )
   else
      $bBusy = 1
      logwrite( "   t2: работа 7 c..." )
      wait( 7 )
      logwrite( "   t2: ... завершена" )
      $bBusy = 0
      wait( 2 )
   end_if
end_thread

logshow(1)
logclear

$bBusy = 0
wait(1)
logwrite( "start threads" )
//wait(1)
setthread (t1, 1)
setthread (t2, 1)

while (1)
   wait( 10 )
end_cyc
halt
[/spoiler]
[spoiler=лог]20:16:59 start threads
20:16:59 t1: работа 5 c...
20:16:59    t2: работа 7 c...
20:17:04 t1: ... завершена
20:17:06    t2: ... завершена
20:17:06 t1: работа 5 c...
20:17:08    t2: жду
20:17:09    t2: жду
20:17:10    t2: жду
20:17:11 t1: ... завершена
20:17:11    t2: работа 7 c...
20:17:13 t1: жду
20:17:14 t1: жду
20:17:15 t1: жду
20:17:16 t1: жду
20:17:17 t1: жду
20:17:18    t2: ... завершена
20:17:18 t1: работа 5 c...
20:17:20    t2: жду
20:17:21    t2: жду
20:17:22    t2: жду
20:17:23 t1: ... завершена
20:17:23    t2: жду
20:17:24    t2: работа 7 c...
20:17:25 t1: жду
[/spoiler]

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Я думаю, потому, что при старте они синхронно вскакивают внутрь условия. Т.е. успевают проверить переменную $bBusy до того как она станет 1 в другом потоке. Ведь код в начале одинаковый и время выполнения одинаковое.
Достаточно один из потоков при старте чуть тормознуть
Code: (clickermann) [Select]
thread(t2, 0)
   WAITMS(5)
...
лог:
Code: [Select]
9:55:42 start threads
9:55:42 t1: работа 5 c...
9:55:42    t2: жду
9:55:43    t2: жду
9:55:44    t2: жду
9:55:45    t2: жду
9:55:47    t2: жду
9:55:47 t1: ... завершена
9:55:48    t2: работа 7 c...
9:55:49 t1: жду
9:55:50 t1: жду
9:55:51 t1: жду
9:55:52 t1: жду
9:55:53 t1: жду
9:55:54 t1: жду
9:55:55    t2: ... завершена
9:55:55 t1: работа 5 c...

5 мс - ничто... Можно тормознуть и при старте
Code: (clickermann) [Select]
setthread (t1, 1)
WAITMS(5)
setthread (t2, 1)
« Last Edit: November 20, 2014, 10:03:28 AM by Vint »


i0

  • Оплот сообщества
  • ****
  • Posts: 353
  • CMann 4.13.014 final, ie, presto, win7 x86, x64
    • View Profile
вот я тоже опытным путём пришёл к wait при старте

но если "они синхронно ... успевают проверить переменную $bBusy до того как она станет 1 в другом потоке", где гарантия, что такая ситуация не может повториться в процессе работы?

quant13

  • Активный участник
  • ***
  • Posts: 174
    • View Profile
Если у тебя одна переменная для проверки на все потоки то никаких гарантий. Сам себя загнал в угол. Не может быть рассинхронизации абсолютной, рано или поздно потоки сойдутся в выполнении на 1 итерацию, по грубым подсчетам каждые 63 сек.
Хотя судя по скрипту я вообще не пойму зачем эти потоки, у тебя выполняется один поток, во время его выполнения второй должен останавливаться, не проще это сделать обычным способом? Одна подпрограмма, потом другая, они и так по-очереди выполнятся будут.
« Last Edit: November 20, 2014, 12:03:51 PM by quant13 »

i0

  • Оплот сообщества
  • ****
  • Posts: 353
  • CMann 4.13.014 final, ie, presto, win7 x86, x64
    • View Profile
Если у тебя одна переменная для проверки на все потоки то никаких гарантий.

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

да, мою задачу можно реализовать без потоков (как уже сделано), но с потоками, имеющими собственные таймеры, всё гораздо красивее в коде

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Красивей то красивей, но как то не по людски. Сначала ввести параллельность, а потом героически с ней бороться. Потоки только ради использования потоков... сомнительно.
Красивее будет вывести в подпрограммы и отдельный переборщик таймеров в цикле. Всё удобно искать и настраивать.


i0

  • Оплот сообщества
  • ****
  • Posts: 353
  • CMann 4.13.014 final, ie, presto, win7 x86, x64
    • View Profile
Красивее будет вывести в подпрограммы и отдельный переборщик таймеров в цикле. Всё удобно искать и настраивать.
так уже реализовано. теперь хочу поизвращаться с применением потоков

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Тогда лучше выбрать более подходящую задачу.