FreeBASIC MutexCreate
目次→実行時ライブラリー参考→多重スレッド化サポート→MUTEXCREATE←オリジナル・サイト
スレッドの実行を同期化させるために使われる、ミューテックス(Mutex:MUTual EXclusion:相互排他) を作成します。
構文:
用法:
result = Mutexcreate
戻り値:
作成されたミューテックスの
any ptr ハンドル。失敗の場合は、ヌルポインタ (0)。
記述:
Mutexe(ミューテックス)とは、"Mutually Exclusive" (互いに排他的である)の短縮表記で、スレッド内の共有データを同期させる方法です。
複数のスレッドで使われるグローバル変数がある(または、単一スレッドで使われる局所静的変数でも、複数回呼ばれる)場合は、変数は、使われている間、ミューテックスで「ロック」する必要があります。
これにより、すべてのスレッド(主プログラムを実行する暗黙のメインスレッドを含む)は、そのミューテックスで、
Mutexunlock でロックが解除されるまで、
Mutexlock を使って停止します。
Mutexcreate は、ミューテックスを作成します。そして、ミューテックスを、ロックするか、錠を開けるか、破壊するとき、参照されるハンドルを返します。
Mutexcreate で作成されるミューテックスは、これ以上は必要なくなるか、あるいは、プログラムの終了前に、
Mutexdestroy で破壊されなければなりません。
ミューテックは、以下の 3つを保証するロックです:
1. アトミック性(不可分性) - ミューテックスをロックすることは、原子(不可分)操作です。この意味は、あなたがミューテックスをロックしたなら、他のどんなスレッドも、同時にこのミューテックスをロックできないことを、オペレーティング・システム(または、スレッド化されたライブラリ)が、保証することです。
2. 単独性 - スレッドがミューテックスをロックしたなら、他のどのスレッドも、元のスレッドがロックを解除するまで、スレッドをロックできないことが、保証されます。
3. 非使用中の待機 - 2番目のスレッドによってロックされたスレッドを、1番目のスレッドがロックしようとすると、1番目のスレッドは、2番目のスレッドがロックを解放するまで、中断されます。このとき、どんな CPU リソースも消費しません。
2番目のスレッドがロックを解放すると、1番目のスレッドは、目覚めて、実行を続けます。こんどは、この1番目のスレッドがミューテックスをロックします。
例:
'ミューテックスを使って、2つのスレッド間の相互排他の目に見える例:
'"user-defined thread" は、円上の点の座標を計算します。
'"main thread" は、点を打点します。
'
'Principle of mutual exclusion
' Thread#A XOR Thread#B
'..... .....
'MutexLock(mut) MutexLock(mut)
' Do_something#A_with_exclusion Do_something#B_with_exclusion
'MutexUnlock(mut) MutexUnlock(mut)
'..... .....
'
'Behavior:
'- The first point must be pre-calculated.
'- Nothing prevents that a same calculated point could be plotted several times
'(depends on execution times of the loops between main thread and user thread).
'- Nothing prevents that a calculated point could be not plotted
'(same remark on the loop times).
'
'If you comment out the lines containing "MutexLock" and "MutexUnlock"
'(inside "user-defined thread" or/and "main thread"),
'there will be no longer mutual exclusion between computation of coordinates and plotting of points,
'and many points will not be plotted on circle (due to non coherent coordinates).
'-----------------------------------------------------------------------------------------------------
Type ThreadUDT 'Generic user thread UDT
Dim handle As Any Ptr 'Any Ptr handle to user thread
Dim sync As Any Ptr 'Any Ptr handle to mutex
Dim quit As Byte 'Boolean to end user thread
Declare Static Sub Thread (ByVal As Any Ptr) 'Generic user thread procedure
Dim procedure As Sub (ByVal As Any Ptr) 'Procedure(Any Ptr) to be executed by user thread
Dim p As Any Ptr 'Any Ptr to pass to procedure executed by user thread
Const false As Byte = 0 'Constante "false"
Const true As Byte = Not false 'Constante "true"
End Type
Static Sub ThreadUDT.Thread (ByVal param As Any Ptr) 'Generic user thread procedure
Dim tp As ThreadUDT Ptr = param 'Casting to generic user thread UDT
Do
Static As Integer I
MutexLock(tp->sync) 'Mutex (Lock) for user thread
tp->procedure(tp->p) 'Procedure(Any Ptr) to be executed by user thread
I += 1
Locate 30, 38
Print I;
MutexUnlock(tp->sync) 'Mutex (Unlock) for user thread
Sleep 5, 1
Loop Until tp->quit = tp->true 'Test for ending user thread
End Sub
'-----------------------------------------------------------------------------------------------------
Type Point2D
Dim x As Integer
Dim y As Integer
End Type
Const x0 As Integer = 640 / 2
Const y0 As Integer = 480 / 2
Const r0 As Integer = 200
Const pi As Single = 4 * Atn(1)
Sub PointOnCircle (ByVal p As Any Ptr)
Dim pp As Point2D Ptr = p
Dim teta As Single = 2 * pi * Rnd
pp->x = x0 + r0 * Cos(teta)
Sleep 5, 1 '無相関データが発生する可能性を高めます
pp->y = y0 + r0 * Sin(teta)
End Sub
Screen 12
Locate 30, 2
Print "<any_key> : exit";
Locate 30, 27
Print "calculated:";
Locate 30, 54
Print "plotted:";
Dim Pptr As Point2D Ptr = New Point2D
PointOnCircle(Pptr) ' 円上で有効な最初の点を計算
Dim Tptr As ThreadUDT Ptr = New ThreadUDT
Tptr->sync = MutexCreate
Tptr->procedure = @PointOnCircle
Tptr->p = Pptr
Tptr->handle = ThreadCreate(@ThreadUDT.Thread, Tptr)
Do
Static As Integer I
Sleep 5, 1
MutexLock(Tptr->sync) 'Mutex (Lock) for main thread
PSet (Pptr->x, Pptr->y) 'Plotting one point
I += 1
Locate 30, 62
Print I;
MutexUnlock(Tptr->sync) 'Mutex (Unlock) for main thread
Loop Until Inkey <> ""
Tptr->quit = Tptr->true
ThreadWait(Tptr->handle)
MutexDestroy(Tptr->sync)
Delete Tptr
Delete Pptr
Sleep
方言差:
プラットホーム差:
-
FreeBASIC の DOS バージョンは、スレッドを考慮しません。OS がスレッドをサポートしないからです。
-
Linux では、スレッドは、常に作成された順に、開始されます。Win32 では、これを想定できません。
これは、OS の問題で、FreeBASIC の問題ではありません。
QBからの違い:
参照:
ページ歴史:2020-11-30 03:51:19
日本語翻訳:WATANABE Makoto、原文著作者:JofersToonski
