另外两种多线程的同步方法

  CriticalSection(临界区) 和 Mutex(互斥), 这两种同步方法差不多, 只是作用域不同;

  1. CriticalSection(临界区) 类似于只有一个蹲位的公共厕所, 只能一个个地进;
  2. Mutex(互斥) 对象类似于接力赛中的接力棒, 某一时刻只能一个人持有, 谁拿着谁跑.

什么是 Semaphore(信号或叫信号量)

  譬如到银行办业务、或者到车站买票, 原来只有一个服务员, 不管有多少人排队等候, 业务只能一个个地来.
  假如增加了业务窗口, 可以同时受理几个业务呢?
  这就类似与 Semaphore 对象, Semaphore 可以同时处理等待函数(如: WaitForSingleObject)申请的几个线程.

Semaphore 的工作思路

  1、首先要通过 CreateSemaphore(安全设置, 初始信号数, 信号总数, 信号名称) 建立信号对象;

function CreateSemaphore(lpSemaphoreAttributes: PSecurityAttributes;
lInitialCount, lMaximumCount: Longint; lpName: PChar): THandle; stdcall;

  参数四: 和 Mutex 一样, 它可以有个名称, 也可以没有, 本例就没有要名称(nil); 有名称的一般用于跨进程.
  参数三: 信号总数, 是 Semaphore 最大处理能力, 就像银行一共有多少个业务窗口一样;
  参数二: 初始信号数, 这就像银行的业务窗口很多, 但打开了几个可不一定, 如果没打开和没有一样;
  参数一: 安全设置和前面一样, 使用默认(nil)即可.

  2、要接受 Semaphore 服务(或叫协调)的线程, 同样需要用等待函数(如: WaitForSingleObject)排队等候;

function WaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD; stdcall;

  3、当一个线程使用完一个信号, 应该用 ReleaseSemaphore(信号句柄, 1, nil) 让出可用信号给其他线程;

function ReleaseSemaphore(hSemaphore: THandle; lReleaseCount: Longint;
lpPreviousCount: Pointer): BOOL; stdcall;

  参数三: 一般是 nil, 如果给个数字指针, 可以接受到此时(之前)总共闲置多少个信号;
  参数二: 一般是 1, 表示增加一个可用信号;
  如果要增加 CreateSemaphore 时的初始信号, 也可以通过 ReleaseSemaphore.

  4、最后, 作为系统内核对象, 要用 CloseHandle 关闭.

Semaphore使用示例

  在本例中, 每点击按钮, 将建立一个信号总数为 5 的信号对象, 初始信号来自 Edit1; 同时有 5 个线程去排队.

  

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls; type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Edit1KeyPress(Sender: TObject; var Key: Char);
end; var
Form1: TForm1; implementation {$R *.dfm} var
f: Integer; {用这个变量协调一下各线程输出的位置}
hSemaphore: THandle; {信号对象的句柄} function MyThreadFun(p: Pointer): DWORD; stdcall;
var
i,y: Integer;
begin
Inc(f);
y := * f;
if WaitForSingleObject(hSemaphore, INFINITE) = WAIT_OBJECT_ then
begin
for i := to do
begin
Form1.Canvas.Lock;
Form1.Canvas.TextOut(, y, IntToStr(i));
Form1.Canvas.Unlock;
Sleep(); {以免 Canvas 忙不过来}
end;
end;
ReleaseSemaphore(hSemaphore, , nil);
Result := ;
end; procedure TForm1.Button1Click(Sender: TObject);
var
ThreadID: DWORD;
begin
{不知是不是之前创建过 Semaphore 对象, 假如有先关闭}
CloseHandle(hSemaphore);
{创建 Semaphore 对象}
hSemaphore := CreateSemaphore(nil, StrToInt(Edit1.Text), , nil); Self.Repaint;
f := ;
CreateThread(nil, , @MyThreadFun, nil, , ThreadID);
CreateThread(nil, , @MyThreadFun, nil, , ThreadID);
CreateThread(nil, , @MyThreadFun, nil, , ThreadID);
CreateThread(nil, , @MyThreadFun, nil, , ThreadID);
CreateThread(nil, , @MyThreadFun, nil, , ThreadID);
end; {让 Edit 只接受 1 2 3 4 5 五个数}
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if not CharInSet(Key, [''..'']) then Key := #;
end; procedure TForm1.FormCreate(Sender: TObject);
begin
Edit1.Text := '';
end; procedure TForm1.FormDestroy(Sender: TObject);
begin
CloseHandle(hSemaphore);
end; end.

文章出处

  www.cnblogs.com/del/archive/2009/02/14/1390747.html

最新文章

  1. 使用sp_xml_preparedocument处理XML文档
  2. GJM:C# WinForm开发系列 - DataGridView 使用方法集锦 [转载]
  3. javascript --- 词法分析
  4. 【BZOJ 3524】【Poi2014】Couriers 可持久化线段树
  5. Node Security
  6. 网站如何提高PR值
  7. 怎样用通用pe工具箱制作U盘启动盘
  8. adb logcat命令查看并过滤android输出log
  9. iOS开发-OC语言 (七)继承、多态、类别
  10. 已经在Git Server服务器上导入了SSH公钥,可用TortoiseGit同步代码时,还是提示输入密码?
  11. invalidate和requestLayout
  12. 无向图的 DFS 和 BFS实现 (以邻接表存储的图)
  13. 如何替代即将淘汰的Flash方案?
  14. python及扩展程序安装
  15. ubuntu16.04 LTS Server 安装mysql phpmyadmin apache2 php5.6环境
  16. Scrum Meeting 13 -2014.11.19
  17. css美化、优化、合并工具推荐
  18. springcloud 笔记-服务注册中心
  19. MqttNet 通讯
  20. Docker Container同时启动多服务 supervisor

热门文章

  1. los中预览文件
  2. apache日志记录格式LogFormat参数说明
  3. TestNg的IReporter接口的使用
  4. VS2010编译Boost 1.56
  5. 在Hadoop1.2.1上运行第一个Hadoop程序FileSystemCat
  6. Linux下面安装和配置MySQL
  7. 【webservice】使用命令wsimport构建WebService客户端
  8. itunes Connect 未能创建 App 图标
  9. 【OpenCV】给图像加入噪声
  10. ELK日志相关