CriticalSectionクラス
提供:AB開発Wiki
(CriticalSection クラスから転送)
ナビゲーションに移動検索に移動
CriticalSectionクラスは、Windowsのクリティカルセクションをラップするクラスです。
クリティカルセクションは、スレッド間で同期を取るためのWin32オブジェクトの1つです。
クラスの機能
継承するインタフェース
メソッド
コンストラクタ
Sub CriticalSection()
デストラクタ
Sub ~CriticalSection()
Disposeを呼びます。
Dispose
クリティカルセクションオブジェクトを解放します。
Sub Dispose()
Enter
クリティカルセクションへ入ります。
Function Enter() As CriticalSectionLock
- 戻り値
- CriticalSectionLockクラスのインスタンス
このメソッドは、クリティカルセクションの所有権を得るまで待機します。
例
まずはクリティカルセクションを使用せず、データに異常を来たす例です。
#console
#require <Classes/System/Threading/Thread.ab>
'共有資源
Type StringData
str[16] As TCHAR
len As SIZE_T
End Type
Dim data As StringData
Function TestProc(args As VoidPtr) As Long
Do
Dim buf[16] As TCHAR
Dim i As Long
Dim s = Nothing As String
'異常を発生させやすくするため、わざと時間をかけて処理する
With data
For i = 0 To ELM(.len)
buf[i] = .str[i]
Sleep(60)
Next
s = New String(buf, .len As Long)
End With
Print s
Sleep(0)
Loop
End Function
Sub SetStringData(ByRef data As StringData)
'出力文字列の変更
With data
lstrcpy(.str, ToTCStr("de"))
.len = lstrlen(.str)
End With
End Sub
With data
lstrcpy(.str, ToTCStr("abc"))
.len = lstrlen(.str)
End With
Dim t As Thread(AddressOf(TestProc),0)
t.Start()
Sleep(1000)
SetStringData(data)
Sleep(-1)
これを実行すると、例えば次のように出力されることがあります(常にこうなるとは限りません)。
abc abc ae de de de
この場合では3行目の出力が異常なものになっています。これは、複数のスレッドが同時に変数strとlenを操作していることが原因です。
これをクリティカルセクションで保護すると次のようになります。
#console
#require <Classes/System/Threading/Thread.ab>
#require <Classes/ActiveBasic/Windows/CriticalSection.ab>
'共有資源
Type StringData
str[16] As TCHAR
len As SIZE_T
End Type
Dim data As StringData
Dim cs = New ActiveBasic.Windows.CriticalSection
Function TestProc(args As VoidPtr) As Long
Do
Dim buf[16] As TCHAR
Dim i As Long
Dim s = Nothing As String
Dim lock = cs.Enter
With data
For i = 0 To ELM(.len)
buf[i] = .str[i]
Sleep(60)
Next
s = New String(buf, .len As Long)
End With
lock.Leave()
Print s
Sleep(0)
Loop
End Function
Sub SetStringData(ByRef data As StringData)
Dim lock = cs.Enter
With data
lstrcpy(.str, ToTCStr("de"))
.len = lstrlen(.str)
End With
lock.Leave()
End Sub
With data
lstrcpy(.str, ToTCStr("abc"))
.len = lstrlen(.str)
End With
Dim t As Thread(AddressOf(TestProc),0)
t.Start()
Sleep(1000)
SetStringData(data)
Sleep(-1)
今度は行単位でデータの整合性が取れた出力になっています。
abc abc abc de de de de de de