MUTEXCREATE
- 来源: https://www.freebasic.net/wiki/wikka.php?wakka=KeyPgMutexCreate
- 最后更新: 2020-11-30
创建用于同步线程执行的互斥锁
语法
declare function Mutexcreate ( ) as any ptr用法
result = Mutexcreate返回值
创建的互斥锁的 any ptr 句柄,失败时返回空指针(0)。
说明
互斥锁(Mutex,即"Mutually Exclusive"的缩写)是一种在线程间同步共享数据的方式。如果有一个全局变量被多个线程使用(或一个静态局部变量被单个线程多次调用),在使用期间应当通过互斥锁对其进行"加锁"。这会阻塞所有使用 Mutexlock 对该互斥锁加锁的线程(包括执行主程序的隐式主线程),直到该互斥锁被 Mutexunlock 解锁。
Mutexcreate 创建一个互斥锁,返回一个句柄,用于后续的加锁、解锁或销毁操作。使用 Mutexcreate 创建的互斥锁在不再需要时或程序结束前应使用 Mutexdestroy 销毁。
互斥锁是一种锁,可保证以下三点:
原子性 - 对互斥锁加锁是一个原子操作,意味着操作系统(或线程库)保证:如果你成功对一个互斥锁加锁,则同时不会有其他线程也成功对该互斥锁加锁。
唯一性 - 如果一个线程成功对互斥锁加锁,可以保证在该线程释放锁之前,没有其他线程能够对该互斥锁加锁。
非忙等待 - 如果一个线程尝试对已被另一个线程加锁的互斥锁加锁,第一个线程将被挂起(不会消耗任何 CPU 资源),直到第二个线程释放锁。此时,第一个线程将被唤醒并继续执行,持有该互斥锁的锁。
示例
另请参见 Threadcreate 的示例。
vb
'使用 Mutex 实现两个线程间互斥的可视化示例:
'"用户定义线程"计算圆上各点的坐标,
'"主线程"绘制这些点。
'
'互斥原理
' 线程#A XOR 线程#B
'..... .....
'MutexLock(mut) MutexLock(mut)
' 带互斥的操作#A 带互斥的操作#B
'MutexUnlock(mut) MutexUnlock(mut)
'..... .....
'
'行为:
'- 第一个点必须预先计算。
'- 不能防止同一个计算点被多次绘制
'(取决于主线程和用户线程之间循环的执行时间)。
'- 不能防止某个计算点没有被绘制
'(同样取决于循环时间)。
'
'如果注释掉包含"MutexLock"和"MutexUnlock"的行
'(在"用户定义线程"或/和"主线程"中),
'坐标计算与点的绘制之间将不再保持互斥,
'许多点将不会被绘制在圆上(因为坐标数据不一致)。
'-----------------------------------------------------------------------------------------------------
Type ThreadUDT '通用用户线程 UDT
Dim handle As Any Ptr '用户线程的 Any Ptr 句柄
Dim sync As Any Ptr '互斥锁的 Any Ptr 句柄
Dim quit As Byte '结束用户线程的布尔值
Declare Static Sub Thread (ByVal As Any Ptr) '通用用户线程过程
Dim procedure As Sub (ByVal As Any Ptr) '由用户线程执行的过程(Any Ptr)
Dim p As Any Ptr '传递给用户线程执行过程的 Any Ptr
Const false As Byte = 0 '常量 "false"
Const true As Byte = Not false '常量 "true"
End Type
Static Sub ThreadUDT.Thread (ByVal param As Any Ptr) '通用用户线程过程
Dim tp As ThreadUDT Ptr = param '转换为通用用户线程 UDT
Do
Static As Integer I
MutexLock(tp->sync) '用户线程的互斥锁(加锁)
tp->procedure(tp->p) '执行用户线程的过程(Any Ptr)
I += 1
Locate 30, 38
Print I;
MutexUnlock(tp->sync) '用户线程的互斥锁(解锁)
Sleep 5, 1
Loop Until tp->quit = tp->true '检测是否结束用户线程
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) '主线程的互斥锁(加锁)
PSet (Pptr->x, Pptr->y) '绘制一个点
I += 1
Locate 30, 62
Print I;
MutexUnlock(Tptr->sync) '主线程的互斥锁(解锁)
Loop Until Inkey <> ""
Tptr->quit = Tptr->true
ThreadWait(Tptr->handle)
MutexDestroy(Tptr->sync)
Delete Tptr
Delete Pptr
Sleep另请参见类似的 Condcreate 示例
方言差异
- 在 -lang qb 方言中不允许使用线程。
平台差异
- FreeBASIC 的 DOS 版本不支持线程,因为操作系统不支持。
- 在 Linux 中,线程始终按创建顺序启动,这在 Win32 中无法保证。这是操作系统的问题,而非 FreeBASIC 的问题。
与 QB 的区别
- FreeBASIC 新增功能
另请参见
MutexdestroyMutexlockMutexunlockThreadcreateThreadwait
返回 目录