CriticalSectionクラス
提供:AB開発Wiki
ナビゲーションに移動検索に移動
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