跳转到内容

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 的旧值

华夏公益教科书