purebasic.info
http://purebasic.info/phpBB3ex/

Потоки (блокировка общего буфера)
http://purebasic.info/phpBB3ex/viewtopic.php?f=5&t=2857
Страница 1 из 2

Автор:  Lunatic [ Пн дек 31, 2012 2:38 am ]
Заголовок сообщения:  Потоки (блокировка общего буфера)

Че-то не разберусь я никак с блокировками потоков

Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Structure PARAM
  Caption$
  Text$
EndStructure
 
Global Mutex=CreateMutex()
 
Procedure AutoCloseMsgBox(*P.PARAM)
  MessageRequester(*P\Caption$,*P\Text$)
EndProcedure
 
Procedure MsgBox(*P.PARAM)
  Protected hThread
  hThread=CreateThread(@AutoCloseMsgBox(),*P)
  Delay(3000)
  If IsThread(hThread)
    KillThread(hThread)
  EndIf
EndProcedure
 
Define *P.PARAM
*P.PARAM= AllocateMemory(SizeOf(PARAM))
 
For i= 0 To 20
  ;LockMutex(Mutex)
  *P\Caption$= Str(I)
  CreateThread(@MsgBox(),*P)
  ;UnlockMutex(Mutex)
  Delay(100)               ;Но если без этого то беда
Next i
 
Delay(5000)
FreeMemory(*P)



Вся соль в том чтобы дождаться потоку пока создастся messagerequester использующий буфер для хранения параметров. во избежание дублирования.

Многопоточность в настройках включил

Автор:  Пётр [ Пн дек 31, 2012 10:46 am ]
Заголовок сообщения: 

Lunatic писал(а):
Вся соль в том чтобы дождаться потоку пока создастся messagerequester
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Structure PARAM 
  Caption$
  Text$
EndStructure
 
Global Mutex=CreateMutex()
 
Procedure AutoCloseMsgBox(*P.PARAM)
  MessageRequester(*P\Caption$,*P\Text$)
EndProcedure
 
Procedure MsgBox(*P.PARAM)
  Protected hThread
  hThread=CreateThread(@AutoCloseMsgBox(),*P)
  ;Delay(3000)
  WaitThread(hThread, 3000)
  If IsThread(hThread)
    KillThread(hThread)
  EndIf
EndProcedure
 
Define *P.PARAM
*P.PARAM= AllocateMemory(SizeOf(PARAM))
 
For i= 0 To 20
  ;LockMutex(Mutex)
  *P\Caption$= Str(I)
  th=CreateThread(@MsgBox(),*P)
  WaitThread(th)
  ;UnlockMutex(Mutex)
  ;Delay(100)               ;Но если без этого то беда
Next i
 
Delay(5000)
FreeMemory(*P)


Автор:  Lunatic [ Пн дек 31, 2012 1:42 pm ]
Заголовок сообщения: 

Эффект немного не тот)) Получилось последовательный вывод сообщения. Второе выводится после завершения первого. Но всё же спасибо. Буду думать, но уже скорее всего в следующем году. Всех с наступающими

Автор:  Пётр [ Пн дек 31, 2012 2:04 pm ]
Заголовок сообщения: 

Почему тогда не выделять отдельный буфер под каждое сообщение?

В крайнем случае, можно поступить следующим образом:
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Structure PARAM 
  Caption$
  Text$
EndStructure
 
Global Semaphore=CreateSemaphore(1)
 
Procedure AutoCloseMsgBox(*P.PARAM)
  Protected Text.PARAM
  CopyStructure(*P, @Text, PARAM)
  SignalSemaphore(Semaphore)
  MessageRequester(Text\Caption$,Text\Text$)
EndProcedure
 
Procedure MsgBox(*P.PARAM)
  Protected hThread
  hThread=CreateThread(@AutoCloseMsgBox(),*P)
  WaitThread(hThread, 3000)
  If IsThread(hThread)
    KillThread(hThread)
  EndIf
EndProcedure
 
Define *P.PARAM
*P.PARAM= AllocateMemory(SizeOf(PARAM))
 
For i= 0 To 20  
  WaitSemaphore(Semaphore)
  *P\Caption$= Str(I)
  th=CreateThread(@MsgBox(),*P)
Next i
 
Delay(5000)
FreeMemory(*P)



А еще лучше сделать так, потому что в первом варианте возможна утечка памяти, если поток будет прибиваться по таймауту.
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Structure PARAM 
  Caption$
  Text$
EndStructure
 
Global Semaphore=CreateSemaphore(1)
 
Procedure AutoCloseMsgBox(*P.PARAM)
  MessageRequester(*P\Caption$,*P\Text$)
EndProcedure
 
Procedure MsgBox(*P.PARAM)
  Protected hThread  
  Protected Text.PARAM
  CopyStructure(*P, @Text, PARAM)
  SignalSemaphore(Semaphore)
  hThread=CreateThread(@AutoCloseMsgBox(),@Text)
  WaitThread(hThread, 3000)
  If IsThread(hThread)
    KillThread(hThread)
  EndIf
EndProcedure
 
Define *P.PARAM
*P.PARAM= AllocateMemory(SizeOf(PARAM))
 
For i= 0 To 20  
  WaitSemaphore(Semaphore)
  *P\Caption$= Str(I)
  th=CreateThread(@MsgBox(),*P)
Next i
 
Delay(5000)
FreeMemory(*P)


Автор:  Lunatic [ Пн дек 31, 2012 4:02 pm ]
Заголовок сообщения: 

О) То что нужно. За CopyStructure я и не подумал. Это вроде новая фишка, почему-то я раньше с ней не сталкивался

Автор:  Пётр [ Пн дек 31, 2012 6:48 pm ]
Заголовок сообщения: 

Lunatic писал(а):
Это вроде новая фишка
Не такая уж она и новая. Функция появилась два года назад в версии 4.50.

Автор:  Gregory [ Пт янв 11, 2019 6:38 pm ]
Заголовок сообщения:  Re: Потоки (блокировка общего буфера)

Вот, добрался до потоков.
Понял, что надо использовать мьютекс.
Вот только не совсем понятно, как его использовать.
Например, основная программа и дополнительный поток используют две переменные. Достаточно ли один раз создать Global Mutex=CreateMutex(), или надо для каждой переменной создавать свой?
Задача посложнее.
Основная программа и дополнительный поток используют одну переменную, два других дополнительных потока используют другую. Вопрос тот же: достаточно ли один раз создать Global Mutex=CreateMutex(), или надо для
каждой переменной создавать свой?

Автор:  Пётр [ Сб янв 12, 2019 12:41 am ]
Заголовок сообщения:  Re: Потоки (блокировка общего буфера)

Gregory писал(а):
основная программа и дополнительный поток используют две переменные.
Получать атомарный доступ к простым переменным обычно нет необходимости, но бывают исключения. Все зависит от того для какой цели используется переменная. А вот для доступа к строковым переменным, спискам и ассоциативным массивам, использование мьютекса обязательно.

Gregory писал(а):
Достаточно ли один раз создать Global Mutex=CreateMutex(), или надо для каждой переменной создавать свой?
Нужно ориентироваться по ситуации. Если переменных 1500, для каждой создавать мьютекс это перебор.
В большинстве случаев одного мьютекса будет достаточно.

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

Автор:  Gregory [ Сб янв 12, 2019 1:39 pm ]
Заголовок сообщения:  Re: Потоки (блокировка общего буфера)

Пётр писал(а):
использование мьютекса обязательно
Так а кто спорит?
Просто хочу понять как этим всем пользоваться. :lol:

Пётр писал(а):
Если один поток захватил мьютекс то остальные при попытке захвата будут ждать его освобождения
Кажется начинаю малость понимать.
Т.е. когда поток включает мьютекс, то все данные, которые он использует (так понимаю, это только глобальные, ибо остальные другим процедурам не доступны) блокируются и недоступны другим потокам. Именно ВСЕ, а не какая-то отдельная переменная, перед которой этот мьютекс был включён.

Автор:  Пётр [ Сб янв 12, 2019 3:10 pm ]
Заголовок сообщения:  Re: Потоки (блокировка общего буфера)

Gregory писал(а):
Т.е. когда поток включает мьютекс, то все данные, которые он использует (так понимаю, это только глобальные, ибо остальные другим процедурам не доступны) блокируются и недоступны другим потокам.
Нет не так. Только один поток может захватить мьютекс, а другие при попытке захвата будут ждать освобождения.
Простой пример.
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
CompilerIf #PB_Compiler_Thread = 0
  CompilerError "Включите поддержку многопоточности в настроках компилятора"
CompilerEndIf
 
Global Mutex = CreateMutex()
Global x=0
 
Procedure Th1(Param)
  Repeat
    LockMutex(Mutex)
    x+1
    Delay(1000)
    UnlockMutex(Mutex)
    Delay(2)
  ForEver
EndProcedure
 
Procedure Th2(Param)
  Repeat
    LockMutex(Mutex)
    Debug "!!!!!!!! Поток 2  x="+x
    UnlockMutex(Mutex)
    Delay(4)
  ForEver
EndProcedure
 
Procedure Th3(Param)
  Repeat
    Debug "Поток 3  x="+x
    Delay(200)
  ForEver
EndProcedure
 
CreateThread(@Th1(), 0)
CreateThread(@Th2(), 0)
CreateThread(@Th3(), 0)
 
MessageRequester("", "Нажмите ОК чтобы закрыть программу")

Пока поток 1 удерживает мьютекс захваченным, поток 2 не может его захватить и при попытке, повиснет в функции LockMutex до тех пор пока не получится захватить. Поток 3 не использует мьютекс и может работать с переменной в любой момент.

Автор:  Gregory [ Сб янв 12, 2019 4:07 pm ]
Заголовок сообщения:  Re: Потоки (блокировка общего буфера)

Пётр писал(а):
повиснет в функции LockMutex
Ах, вот оно чего? :lol:
Т.е. мьютекс, это - некий "объект", который захватывается функцией LockMutex.
А пока она его не захватит, будет продолжать попытки, и программа в этом месте "зависнет".

Автор:  Пётр [ Сб янв 12, 2019 4:17 pm ]
Заголовок сообщения:  Re: Потоки (блокировка общего буфера)

Да, именно так.

Автор:  Gregory [ Сб янв 12, 2019 4:56 pm ]
Заголовок сообщения:  Re: Потоки (блокировка общего буфера)

Ура!
Хоть с одним вопросом разобрались.
Впрочем не совсем.
А чем тогда мьютексы от семафоров отличаются?

Автор:  Пётр [ Сб янв 12, 2019 8:14 pm ]
Заголовок сообщения:  Re: Потоки (блокировка общего буфера)

Поток ждет момента когда семафор будет в сигнальном состоянии. Например если один поток подготавливает данные, а второй обрабатывает их, то первый поток подготовив данные, переводит семафор в сигнальное состояние и второй поток забирает данные.
Пример в котором семафор используется в потоке читающем данные из файла, которые в дальнейшем обрабатывают другие потоки. download/file.php?id=2342

Автор:  Gregory [ Сб янв 12, 2019 9:25 pm ]
Заголовок сообщения:  Re: Потоки (блокировка общего буфера)

Пётр писал(а):
переводит семафор в сигнальное состояние и второй поток забирает данные
Вроде не совсем корректный пример, ибо если второй поток начнёт работать с данными, то он должен их заблокировать для других потоков (т.е. задействовать мьютекс).
Но я вообще-то о другом спрашивал.
Имелось ввиду, что и мьютекс, и семафор выполняют одинаковую функцию, тормозя программу, пока другой поток не разрешит её продолжение.

Страница 1 из 2 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/