purebasic.info

PureBasic forum
Текущее время: Ср июн 19, 2019 6:08 pm

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 19 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Потоки (блокировка общего буфера)
СообщениеДобавлено: Пн дек 31, 2012 2:38 am 
Не в сети
профессор
Аватар пользователя

Зарегистрирован: Сб окт 09, 2010 2:21 am
Сообщений: 326
Откуда: Киев
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Че-то не разберусь я никак с блокировками потоков

Код:
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 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11481
Благодарил (а): 4 раз.
Поблагодарили: 468 раз.
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)


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


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пн дек 31, 2012 1:42 pm 
Не в сети
профессор
Аватар пользователя

Зарегистрирован: Сб окт 09, 2010 2:21 am
Сообщений: 326
Откуда: Киев
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Эффект немного не тот)) Получилось последовательный вывод сообщения. Второе выводится после завершения первого. Но всё же спасибо. Буду думать, но уже скорее всего в следующем году. Всех с наступающими

_________________
Win7 Enterprise x86 (PB 5.11)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пн дек 31, 2012 2:04 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11481
Благодарил (а): 4 раз.
Поблагодарили: 468 раз.
Почему тогда не выделять отдельный буфер под каждое сообщение?

В крайнем случае, можно поступить следующим образом:
Код:
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)


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


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пн дек 31, 2012 4:02 pm 
Не в сети
профессор
Аватар пользователя

Зарегистрирован: Сб окт 09, 2010 2:21 am
Сообщений: 326
Откуда: Киев
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
О) То что нужно. За CopyStructure я и не подумал. Это вроде новая фишка, почему-то я раньше с ней не сталкивался

_________________
Win7 Enterprise x86 (PB 5.11)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пн дек 31, 2012 6:48 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11481
Благодарил (а): 4 раз.
Поблагодарили: 468 раз.
Lunatic писал(а):
Это вроде новая фишка
Не такая уж она и новая. Функция появилась два года назад в версии 4.50.

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


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт янв 11, 2019 6:38 pm 
Не в сети
док

Зарегистрирован: Чт окт 27, 2011 7:43 pm
Сообщений: 136
Откуда: Санкт-Ленинград
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Вот, добрался до потоков.
Понял, что надо использовать мьютекс.
Вот только не совсем понятно, как его использовать.
Например, основная программа и дополнительный поток используют две переменные. Достаточно ли один раз создать Global Mutex=CreateMutex(), или надо для каждой переменной создавать свой?
Задача посложнее.
Основная программа и дополнительный поток используют одну переменную, два других дополнительных потока используют другую. Вопрос тот же: достаточно ли один раз создать Global Mutex=CreateMutex(), или надо для
каждой переменной создавать свой?

_________________
ICQ нет, и, в ближайшее время, не будет


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб янв 12, 2019 12:41 am 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11481
Благодарил (а): 4 раз.
Поблагодарили: 468 раз.
Gregory писал(а):
основная программа и дополнительный поток используют две переменные.
Получать атомарный доступ к простым переменным обычно нет необходимости, но бывают исключения. Все зависит от того для какой цели используется переменная. А вот для доступа к строковым переменным, спискам и ассоциативным массивам, использование мьютекса обязательно.

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

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

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


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб янв 12, 2019 1:39 pm 
Не в сети
док

Зарегистрирован: Чт окт 27, 2011 7:43 pm
Сообщений: 136
Откуда: Санкт-Ленинград
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Пётр писал(а):
использование мьютекса обязательно
Так а кто спорит?
Просто хочу понять как этим всем пользоваться. :lol:

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

_________________
ICQ нет, и, в ближайшее время, не будет


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб янв 12, 2019 3:10 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11481
Благодарил (а): 4 раз.
Поблагодарили: 468 раз.
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 не использует мьютекс и может работать с переменной в любой момент.

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


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб янв 12, 2019 4:07 pm 
Не в сети
док

Зарегистрирован: Чт окт 27, 2011 7:43 pm
Сообщений: 136
Откуда: Санкт-Ленинград
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Пётр писал(а):
повиснет в функции LockMutex
Ах, вот оно чего? :lol:
Т.е. мьютекс, это - некий "объект", который захватывается функцией LockMutex.
А пока она его не захватит, будет продолжать попытки, и программа в этом месте "зависнет".

_________________
ICQ нет, и, в ближайшее время, не будет


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб янв 12, 2019 4:17 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11481
Благодарил (а): 4 раз.
Поблагодарили: 468 раз.
Да, именно так.

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


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб янв 12, 2019 4:56 pm 
Не в сети
док

Зарегистрирован: Чт окт 27, 2011 7:43 pm
Сообщений: 136
Откуда: Санкт-Ленинград
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Ура!
Хоть с одним вопросом разобрались.
Впрочем не совсем.
А чем тогда мьютексы от семафоров отличаются?

_________________
ICQ нет, и, в ближайшее время, не будет


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб янв 12, 2019 8:14 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11481
Благодарил (а): 4 раз.
Поблагодарили: 468 раз.
Поток ждет момента когда семафор будет в сигнальном состоянии. Например если один поток подготавливает данные, а второй обрабатывает их, то первый поток подготовив данные, переводит семафор в сигнальное состояние и второй поток забирает данные.
Пример в котором семафор используется в потоке читающем данные из файла, которые в дальнейшем обрабатывают другие потоки. download/file.php?id=2342

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


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб янв 12, 2019 9:25 pm 
Не в сети
док

Зарегистрирован: Чт окт 27, 2011 7:43 pm
Сообщений: 136
Откуда: Санкт-Ленинград
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Пётр писал(а):
переводит семафор в сигнальное состояние и второй поток забирает данные
Вроде не совсем корректный пример, ибо если второй поток начнёт работать с данными, то он должен их заблокировать для других потоков (т.е. задействовать мьютекс).
Но я вообще-то о другом спрашивал.
Имелось ввиду, что и мьютекс, и семафор выполняют одинаковую функцию, тормозя программу, пока другой поток не разрешит её продолжение.

_________________
ICQ нет, и, в ближайшее время, не будет


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 19 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: AZJIO, Bing [Bot] и гости: 5


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group (блог о phpBB)
Сборка создана CMSart Studio
Русская поддержка phpBB