跳轉到內容

BlitzMax/Modules/System/Threads

來自華夏公益教科書

歡迎來到多執行緒的奇妙世界!

多執行緒實際上允許您的程式同時執行多項任務。在此上下文中,“執行緒”指的是“執行執行緒” - 或者,您的程式執行的一系列指令、分支等等。大多數程式都是“單執行緒”的,這意味著只有一條執行執行緒。但是,越來越多的程式正在使用多執行緒。

多執行緒曾經是透過軟體技巧實現的,這使得多執行緒變得有用,但並沒有真正加快速度 - 仍然只有一個 CPU 假裝同時執行多項任務!但是如今,多核 CPU 意味著多執行緒可以真正地同時執行多項任務(或“並行”)。

建立執行緒很容易 - 只需呼叫 CreateThread 即可。您需要為執行緒提供一個用作其“入口點”的函式。建立執行緒後,該函式將與呼叫 CreateThread 的程式碼並行執行。當執行緒函式返回時,該執行緒將“終止”。

唉,多執行緒由於一個稱為“同步”的問題而變得相當棘手。當您需要防止多個執行緒同時修改或訪問相同的資料時,需要同步。同步通常涉及執行緒“阻塞”。當執行緒阻塞時,它會完全停止執行,直到另一個執行緒執行導致它“解除阻塞”並恢復執行的操作。

BlitzMax 提供了兩個稱為“互斥鎖”和“訊號量”的基本原語來幫助同步。

  • 互斥鎖提供了一個簡單的鎖定機制。一次只有一個執行緒可以鎖定一個互斥鎖(使用 LockMutexTryLockMutex),因此這是一種輕鬆保護資源免受同時訪問的方法。如果一個執行緒呼叫 LockMutex 並且互斥鎖已被另一個執行緒鎖定,則當前執行緒將阻塞,直到另一個執行緒使用 UnlockMutex 釋放互斥鎖。因此,請不要忘記在完成互斥鎖後使用 UnlockMutex 釋放它!
  • 訊號量提供了一種同步計數機制,幷包含一個內部整數計數器。您可以對訊號量執行兩種操作 - 傳送和等待。傳送訊號量(使用 PostSemaphore)會導致訊號量的內部計數器遞增,而等待訊號量(使用 WaitSemaphore)會導致當前執行緒阻塞,直到訊號量的內部計數器大於 0。當計數器大於 0 時,計數器會遞減,並且執行緒會解除阻塞。訊號量對於生產者/消費者型別的情況非常有用。

執行緒型別

方法
  • Detach
  • Wait
  • Running
函式
  • Create
  • Main
  • Current

TThread:方法

[編輯 | 編輯原始碼]
Detach

方法 Detach()

描述:分離此執行緒

Wait

方法 Wait:Object()

描述:等待此執行緒完成

返回值:執行緒返回的物件。

Running

方法 Running()

描述:檢查此執行緒是否正在執行

TThread:函式

[編輯 | 編輯原始碼]
Create

函式 Create:TThread( entry:Object( data:Object),data:Object )

描述:建立一個新執行緒

Main

函式 Main:TThread()

描述:獲取主執行緒

返回值:一個表示主應用程式執行緒的執行緒物件。

Current

函式 Current:TThread()

描述:獲取當前執行緒

返回值:一個表示當前執行緒的執行緒物件。

TThreadData

[編輯 | 編輯原始碼]

執行緒資料型別

方法
  • SetValue
  • GetValue
函式
  • Create

TThreadData:方法

[編輯 | 編輯原始碼]
SetValue

方法 SetValue( value:Object )

描述:設定執行緒資料值

GetValue

方法 GetValue:Object()

描述:獲取執行緒資料值

TThreadData:函式

[編輯 | 編輯原始碼]
Create

函式 Create:TThreadData()

描述:建立執行緒資料

互斥鎖型別

方法
  • Close
  • Lock
  • TryLock
  • Unlock
函式
  • Create

TMutex:方法

[編輯 | 編輯原始碼]
Close

方法 Close()

描述:關閉互斥鎖

Lock

方法 Lock()

描述:鎖定互斥鎖

TryLock

方法 TryLock()

描述: 嘗試鎖定互斥鎖

返回值: 如果互斥鎖成功鎖定,則返回 True;如果互斥鎖已被另一個執行緒鎖定,則返回 False

Unlock

方法 Unlock()

描述: 解鎖互斥鎖

TMutex: 函式

[編輯 | 編輯原始碼]
Create

函式 Create:TMutex()

描述: 建立一個新的互斥鎖

TSemaphore

[編輯 | 編輯原始碼]

訊號量型別

方法
  • Close
  • Wait
  • Post
函式
  • Create

TSemaphore: 方法

[編輯 | 編輯原始碼]
Close

方法 Close()

描述: 關閉訊號量

Wait

方法 Wait()

描述: 等待訊號量

Post

方法 Post()

描述: 釋出訊號量

TSemaphore: 函式

[編輯 | 編輯原始碼]
Create

函式 Create:TSemaphore( count )

描述: 建立一個新的訊號量

條件變數型別

方法
  • Close
  • Wait
  • Signal
  • Broadcast
函式
  • Create

TCondVar: 方法

[編輯 | 編輯原始碼]
Close

方法 Close()

描述: 關閉條件變數

Wait

方法 Wait( mutex:TMutex )

描述: 等待條件變數

Signal

方法 Signal()

描述: 通知條件變數

Broadcast

方法 Broadcast()

描述: 廣播條件變數

TCondVar: 函式

[編輯 | 編輯原始碼]
Create

函式 Create:TCondVar()

描述: 建立一個新的條件變數

CreateThread

[編輯 | 編輯原始碼]

函式 CreateThread:TThread( entry:Object( data:Object ),data:Object )

描述: 建立一個執行緒

返回值: 一個新的執行緒物件。

資訊: 建立一個執行緒並返回一個執行緒物件。

執行緒 entry 例程返回的值可以透過 WaitThread 檢索。

要“關閉”執行緒,請呼叫 DetachThreadWaitThread。這並不是嚴格必要的,因為執行緒最終會在垃圾回收時被關閉,但是,如果您經常建立很多執行緒,這是一個好主意,因為某些作業系統對一次可以分配的執行緒數量有限制。

示例:

'Make sure to have 'Threaded build' enabled!
'
Strict

'Custom print that shows which thread is doing the printing
Function MyPrint( t$ )
	If CurrentThread()=MainThread() 
		Print "Main thread: "+t
	Else
		Print "Child thread: "+t
	EndIf
End Function

'Our thread function
Function MyThread:Object( data:Object )

	'show data we were passed
	Myprint data.ToString()

	'do some work
	For Local i=1 To 1000
		MyPrint "i="+i
	Next
	
	'return a value from the thread
	Return "Data returned from child thread."
	
End Function

MyPrint "About to start child thread."

'create a thread!
Local thread:TThread=CreateThread( MyThread,"Data passed to child thread." )

'wait for thread to finish and print value returned from thread
MyPrint WaitThread( Thread ).ToString()

MainThread

[編輯 | 編輯原始碼]

函式 MainThread:TThread()

描述:獲取主執行緒

返回值: 一個表示主應用程式執行緒的執行緒物件。

CurrentThread

[編輯 | 編輯原始碼]

函式 CurrentThread:TThread()

描述:獲取當前執行緒

返回值:一個表示當前執行緒的執行緒物件。

DetachThread

[編輯 | 編輯原始碼]

函式 DetachThread( thread:TThread )

描述: 分離執行緒

資訊: DetachThread 關閉執行緒控制代碼,但不停止或以其他方式影響目標執行緒。

一旦執行緒被分離,就無法再使用 WaitThread 獲取其返回值。

這允許執行緒執行,而無需您的程式不斷檢查它是否已完成以關閉它。

WaitThread

[編輯 | 編輯原始碼]

函式 WaitThread:Object( thread:TThread )

描述: 等待執行緒完成

返回值: 執行緒入口例程返回的物件。

資訊: WaitThread 導致呼叫執行緒阻塞,直到目標執行緒完成執行。

如果目標執行緒已經完成執行,WaitThread 會立即返回。

返回的物件是執行緒入口例程返回的物件,該物件傳遞給 CreateThread

ThreadRunning

[編輯 | 編輯原始碼]

函式 ThreadRunning( thread:TThread )

描述: 檢查執行緒是否正在執行

返回值: 如果 thread 仍在執行,則返回 True,否則返回 False

CreateThreadData

[編輯 | 編輯原始碼]

函式 CreateThreadData:TThreadData()

描述:建立執行緒資料

返回值: 一個新的執行緒資料物件。

SetThreadDataValue

[編輯 | 編輯原始碼]

函式 SetThreadDataValue( data:TThreadData,value:Object )

描述:設定執行緒資料值

GetThreadDataValue

[編輯 | 編輯原始碼]

函式 GetThreadDataValue:Object( data:TThreadData )

描述:獲取執行緒資料值

CreateMutex

[編輯 | 編輯原始碼]

函式 CreateMutex:TMutex()

描述: 建立一個互斥鎖

返回值: 一個新的互斥鎖物件

示例:

'Make sure to have 'Threaded build' enabled!
'
Strict

'a global list that multiple threads want to modify
Global list:TList=New TList

'a mutex controlling access to the global list
Global listMutex:TMutex=CreateMutex()

Function MyThread:Object( data:Object )

	For Local item=1 To 10
		'simulate 'other' processing...
		Delay Rand( 10,50 )

		'lock mutex so we can safely modify global list
		LockMutex listMutex

		'modify list
		list.AddLast "Thread "+data.ToString()+" added item "+item

		'unlock mutex
		UnlockMutex listMutex
	Next
	
End Function

Local threads:TThread[10]

'Create worker threads
For Local i=0 Until 10
	threads[i]=CreateThread( MyThread,String( i+1 ) )
Next

Print "Waiting for worker threads..."

'Wait for worker threads to finish
For Local i=0 Until 10
	WaitThread threads[i]
Next

'Show the resulting list
'
'Note: We don't really have to lock the mutex here, as there are no other threads running.
'Still, it's a good habit to get into.
LockMutex listMutex
For Local t$=EachIn list
	Print t
Next
UnlockMutex listMutex

CloseMutex

[編輯 | 編輯原始碼]

函式 CloseMutex( mutex:TMutex )

描述: 關閉互斥鎖

LockMutex

[編輯 | 編輯原始碼]

函式 LockMutex( mutex:TMutex )

描述: 鎖定互斥鎖

TryLockMutex

[編輯 | 編輯原始碼]

函式 TryLockMutex( mutex:TMutex )

描述: 嘗試鎖定互斥鎖

返回值: 如果 mutex 成功鎖定,則返回 True;如果 mutex 已被另一個執行緒鎖定,則返回 False

UnlockMutex

[編輯 | 編輯原始碼]

函式 UnlockMutex( mutex:TMutex )

描述: 解鎖互斥鎖

CreateSemaphore

[編輯 | 編輯原始碼]

Function CreateSemaphore:TSemaphore( count )

描述: 建立一個訊號量

返回值: 一個新的訊號量物件

示例:

'Make sure to have 'Threaded build' enabled!
'
Strict

'a simple queue
Global queue$[100],put,get

'a counter semaphore
Global counter:TSemaphore=CreateSemaphore( 0 )

Function MyThread:Object( data:Object )

	'process 100 items
	For Local item=1 To 100
	
		'add an item to the queue
		queue[put]="Item "+item
		put:+1
		
		'increment semaphore count.
		PostSemaphore counter
	
	Next
		
End Function

'create worker thread
Local thread:TThread=CreateThread( MyThread,Null )

'receive 100 items
For Local i=1 To 100

	'Wait for semaphore count to be non-0, then decrement.
	WaitSemaphore counter
	
	'Get an item from the queue
	Local item$=queue[get]
	get:+1
	
	Print item

Next

CloseSemaphore

[編輯 | 編輯原始碼]

Function CloseSemaphore( semaphore:TSemaphore )

描述: 關閉一個訊號量

WaitSemaphore

[編輯 | 編輯原始碼]

Function WaitSemaphore( semaphore:TSemaphore )

描述: 等待一個訊號量

PostSemaphore

[編輯 | 編輯原始碼]

Function PostSemaphore( semaphore:TSemaphore )

描述: 傳送一個訊號量

CreateCondVar

[編輯 | 編輯原始碼]

Function CreateCondVar:TCondVar()

描述: 建立一個條件變數

返回值: 一個新的條件變數物件

CloseCondVar

[編輯 | 編輯原始碼]

Function CloseCondVar( condvar:TCondVar )

描述: 關閉一個條件變數

WaitCondVar

[編輯 | 編輯原始碼]

Function WaitCondVar( condvar:TCondVar,mutex:TMutex )

描述: 等待一個條件變數

SignalCondVar

[編輯 | 編輯原始碼]

Function SignalCondVar( condvar:TCondVar )

描述: 通知一個條件變數

BroadcastCondVar

[編輯 | 編輯原始碼]

Function BroadcastCondVar( condvar:TCondVar )

描述: 廣播一個條件變數

CompareAndSwap

[編輯 | 編輯原始碼]

Function CompareAndSwap( target Var,oldValue,newValue )

描述: 比較並交換

返回值: 如果 target 被更新則返回 True

資訊: 如果 target 等於 old_value,則以原子方式將 target 替換為 new_value

AtomicAdd

[編輯 | 編輯原始碼]

Function AtomicAdd( target Var,value )

描述: 原子加法

返回值: target 的先前值

資訊: 以原子方式將 value 新增到 target

AtomicSwap

[編輯 | 編輯原始碼]

Function AtomicSwap( target Var,value )

描述: 原子交換值

返回值: target 的舊值

華夏公益教科書