Delphi多线程编程1011多线程同步之 Mutex 互斥对象.docx

上传人:b****7 文档编号:10676445 上传时间:2023-02-22 格式:DOCX 页数:11 大小:44.52KB
下载 相关 举报
Delphi多线程编程1011多线程同步之 Mutex 互斥对象.docx_第1页
第1页 / 共11页
Delphi多线程编程1011多线程同步之 Mutex 互斥对象.docx_第2页
第2页 / 共11页
Delphi多线程编程1011多线程同步之 Mutex 互斥对象.docx_第3页
第3页 / 共11页
Delphi多线程编程1011多线程同步之 Mutex 互斥对象.docx_第4页
第4页 / 共11页
Delphi多线程编程1011多线程同步之 Mutex 互斥对象.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

Delphi多线程编程1011多线程同步之 Mutex 互斥对象.docx

《Delphi多线程编程1011多线程同步之 Mutex 互斥对象.docx》由会员分享,可在线阅读,更多相关《Delphi多线程编程1011多线程同步之 Mutex 互斥对象.docx(11页珍藏版)》请在冰豆网上搜索。

Delphi多线程编程1011多线程同步之 Mutex 互斥对象.docx

Delphi多线程编程1011多线程同步之Mutex互斥对象

原理分析:

互斥对象是系统内核对象,各线程都可以拥有它,谁拥有谁就能执行;

执行完毕,用ReleaseMutex函数释放拥有权,以让其他等待的线程使用.

其他线程可用WaitForSingleObject函数排队等候(等候也可以理解为排队申请).

使用过程:

varhMutex:

THandle;{应该先声明一个全局的互斥句柄}

CreateMutex{建立一个互斥对象}

WaitForSingleObject{用等待函数排队等候}

ReleaseMutex{释放拥有权}

CloseHandle{最后释放互斥对象}

ReleaseMutex、CloseHandle的参数都是CreateMutex返回的句柄,关键是CreateMutex函数:

functionCreateMutex(

lpMutexAttributes:

PSecurityAttributes;

bInitialOwner:

BOOL;{是否让创建者(此例中是主线程)拥有该互斥对象}

lpName:

PWideChar{可以给此互斥对象取个名字,如果不要名字可赋值为nil}

):

THandle;

{

1、第一个参数前面说过.

2、第二个参数在这里一定要是False,如果让主线程拥有互斥,从理论上讲,得等程序退出后其他线程才有机会;

取值False时,第一个执行的线程将会最先拥有互斥对象,一旦拥有其他线程就得先等等.

3、第三个参数,如果给个名字,函数将从系统中寻找是否有重名的互斥对象,如果有则返回同名对象的存在的句柄;

如果赋值为nil将直接创建一个新的互斥对象;下个例子将会有名字.}

本例效果图:

代码文件:

unitUnit1;

interface

uses

Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,

Dialogs,StdCtrls;

type

TForm1=class(TForm)

Button1:

TButton;

procedureButton1Click(Sender:

TObject);

procedureFormCreate(Sender:

TObject);

procedureFormDestroy(Sender:

TObject);

end;

var

Form1:

TForm1;

implementation

{$R*.dfm}

var

f:

Integer;{用这个变量协调一下各线程输出的位置}

hMutex:

THandle;{互斥对象的句柄}

functionMyThreadFun(p:

Pointer):

DWORD;stdcall;

var

i,y:

Integer;

begin

Inc(f);

y:

=20*f;

fori:

=0to50000do

begin

ifWaitForSingleObject(hMutex,INFINITE)=WAIT_OBJECT_0then

begin

Form1.Canvas.Lock;

Form1.Canvas.TextOut(20,y,IntToStr(i));

Form1.Canvas.Unlock;

Sleep(0);{稍稍耽搁一点,不然有时Canvas会协调不过来}

ReleaseMutex(hMutex);

end;

end;

Result:

=0;

end;

procedureTForm1.Button1Click(Sender:

TObject);

var

ThreadID:

DWORD;

begin

Repaint;

f:

=0;

CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID);

CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID);

CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID);

CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID);

CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID);

end;

procedureTForm1.FormCreate(Sender:

TObject);

begin

hMutex:

=CreateMutex(nil,False,nil);

end;

procedureTForm1.FormDestroy(Sender:

TObject);

begin

CloseHandle(hMutex);

end;

end.

窗体文件:

objectForm1:

TForm1

Left=0

Top=0

Caption='Form1'

ClientHeight=140

ClientWidth=192

Color=clBtnFace

Font.Charset=DEFAULT_CHARSET

Font.Color=clWindowText

Font.Height=-11

Font.Name='Tahoma'

Font.Style=[]

OldCreateOrder=False

OnCreate=FormCreate

PixelsPerInch=96

TextHeight=13

objectButton1:

TButton

Left=109

Top=107

Width=75

Height=25

Caption='Button1'

TabOrder=0

OnClick=Button1Click

end

end

SyncObjs单元下有封装好的TMutex类,好像不如Api快,内部机制也稍有区别,但使用方法差不多:

unitUnit1;

interface

uses

Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,

Dialogs,StdCtrls;

type

TForm1=class(TForm)

Button1:

TButton;

procedureButton1Click(Sender:

TObject);

procedureFormCreate(Sender:

TObject);

procedureFormDestroy(Sender:

TObject);

end;

var

Form1:

TForm1;

implementation

{$R*.dfm}

usesSyncObjs;

var

f:

Integer;

MyMutex:

TMutex;

functionMyThreadFun(p:

Pointer):

DWORD;stdcall;

var

i,y:

Integer;

begin

Inc(f);

y:

=20*f;

fori:

=0to50000do

begin

ifMyMutex.WaitFor(INFINITE)=wrSignaledthen

begin

Form1.Canvas.Lock;

Form1.Canvas.TextOut(20,y,IntToStr(i));

Form1.Canvas.Unlock;

MyMutex.Release;

end;

end;

Result:

=0;

end;

procedureTForm1.Button1Click(Sender:

TObject);

var

ThreadID:

DWORD;

begin

Repaint;

f:

=0;

CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID);

CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID);

CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID);

CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID);

CreateThread(nil,0,@MyThreadFun,nil,0,ThreadID);

end;

procedureTForm1.FormCreate(Sender:

TObject);

begin

MyMutex:

=TMutex.Create(False);

end;

procedureTForm1.FormDestroy(Sender:

TObject);

begin

MyMutex.Free;

end;

end.

Mutex作为系统核心对象是可以跨进程的(临界区就不行),我们可以利用互斥对象禁止程序重复启动.

工作思路:

先用OpenMutex尝试打开一个自定义名称的Mutex对象,如果打开失败说明之前没有这个对象存在;

如果之前没有这个对象,马上用CreateMutex建立一个,此时的程序应该是第一次启动;

再重复启动时,那个OpenMutex就有结果了,然后强制退出.

最后在程序结束时用CloseHandle释放Mutex对象.

functionOpenMutex(

dwDesiredAccess:

DWORD;{打开权限}

bInheritHandle:

BOOL;{能否被当前程序创建的进程继承}

pName:

PWideChar{Mutex对象的名称}

):

THandle;stdcall;{成功返回Mutex的句柄;失败返回0}

注意,这里的CreateMutex函数应该有个名了,因为OpenMutex要用到;

另外,CreateMutex的第二个参数已经不重要了(也就是True和False都行),因为这里是用其名称来判断的.

程序可以这样写:

unitUnit1;

interface

uses

Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,

Dialogs;

type

TForm1=class(TForm)

procedureFormCreate(Sender:

TObject);

procedureFormDestroy(Sender:

TObject);

end;

var

Form1:

TForm1;

implementation

{$R*.dfm}

var

hMutex:

THandle;

const

NameMutex='MyMutex';

procedureTForm1.FormCreate(Sender:

TObject);

begin

ifOpenMutex(MUTEX_ALL_ACCESS,False,NameMutex)<>0then

begin

ShowMessage('该程序已启动');

Application.Terminate;

end;

hMutex:

=CreateMutex(nil,False,NameMutex);

end;

procedureTForm1.FormDestroy(Sender:

TObject);

begin

CloseHandle(hMutex);

end;

end.

这一般都是写在dpr主程序里,省得让后启动的程序执行些无用的代码:

programProject1;

uses

Forms,Windows,

Unit1in'Unit1.pas'{Form1};

{$R*.res}

var

hMutex:

THandle;

const

NameMutex='MyMutex';

begin

{主线程入口}

ifOpenMutex(MUTEX_ALL_ACCESS,False,NameMutex)<>0then

begin

MessageBox(0,'该程序已启动','提示',MB_OK);

Application.Terminate;

end;

hMutex:

=CreateMutex(nil,False,NameMutex);

Application.Initialize;

Application.MainFormOnTaskbar:

=True;

Application.CreateForm(TForm1,Form1);

Application.Run;

CloseHandle(hMutex);

{主线程出口}

end.

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 教学研究 > 教学案例设计

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1