孤独的猫

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

信号量是建立在互斥量的基础之上,同时加入重要特性:提供了资源计数功能,因此预定义数量的线程同时可以进入同步的代码块中。

      信号量是维护0到指定最大值之间的计数器的同步对象,当线程完成一次信号量的等待时,计数器自减1,当线程释放信号量对象时,计数器自增1。

      借用上面的图书馆例子,信号量好像是多设几把管理钥匙。每次可以设定N把钥匙同时工作,那就有N个人员可以同时办理业务。

     信号量使用的一般步骤:

1、声明一个全局的信号量名柄,如:hSem:THandle;

2、创建信号量:CreateSemphore(

                              lpSemaphoreAttributes:PSecurityAttributes;

                              lInitialCount,lMaximumCount:LongInt;

                              lpName:PChar):THandle;stdcall;

  (lpSemaphoreAttributes参数,指向TSecurityAttributes记录的指针,一般可以缺省填入nil值;

    lInitialCount参数,是信号量对象的初始计数,是0~lMaximumCount之间的数。当它大于0时,信号量就进入了信号状态,当WaiForSingleObject函数释放了一个线程,信号量计数就减1。使用ReleaseSemphore函数可以增加信号量计数;

   lMaximumCount参数,是信号量对象计数的最大值;

   lpName参数,指定信号量的名字。)

3、用等待函数WaiForSingleObject协调线程。

4、当一个线程用完一个信号,释放。使用ReleaseSemphore(

                                                          hSemaphore:THandle;

                                                          lReleaseCount:LongInt;

                                                          lpPreviousCount:Pointer):BOOL;StdCall;

(hSemphore参数,是信号量对象句柄;

   lReleaseCount参数,要增加的信号量计数的数量;

  lpPreviousCount参数,当前资源数量的原始值,一般为nil。)

5、最后关闭信号量句柄,CloseHandle(hSem)。

如果最大信号量计数为1,那么就相当于Mutex。

  {主窗体代码}  
  1. unit Unit2;  
  2.    
  3. interface  
  4.    
  5. uses  
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  7.   Dialogs, StdCtrls;  
  8.    
  9. type  
  10.   TForm2 = class(TForm)  
  11.     Button1: TButton;  
  12.     Label1: TLabel;  
  13.     Label2: TLabel;  
  14.     Label3: TLabel;  
  15.     Label4: TLabel;  
  16.     Label5: TLabel;  
  17.     procedure Button1Click(Sender: TObject);  
  18.     procedure FormCreate(Sender: TObject);  
  19.     procedure FormDestroy(Sender: TObject);  
  20.   private  
  21.     { Private declarations }  
  22.   public  
  23.     { Public declarations }  
  24.   end;  
  25.    
  26. var  
  27.   Form2: TForm2;  
  28.   hSem:THandle;  
  29. implementation  
  30.    
  31. uses MyThread;  
  32.    
  33. {$R *.dfm}  
  34.    
  35. procedure TForm2.Button1Click(Sender: TObject);  
  36. begin  
  37.   TMyThread.Create(Label1);  
  38.   TMyThread.Create(Label2);  
  39.   TMyThread.Create(Label3);  
  40.   TMyThread.Create(Label4);  
  41.   TMyThread.Create(Label5);  
  42. end;  
  43.    
  44. procedure TForm2.FormCreate(Sender: TObject);  
  45. begin  
  46.   hSem:=CreateSemaphore(nil,2,3,nil);  
  47. end;  
  48.    
  49. procedure TForm2.FormDestroy(Sender: TObject);  
  50. begin  
  51.   CloseHandle(hSem);  
  52. end;  
  53.    
  54. end.{多线程类}  
  55. unit MyThread;  
  56.    
  57. interface  
  58.    
  59. uses  
  60.   Classes,StdCtrls,SysUtils,Windows;  
  61.    
  62. type  
  63.   TMyThread = class(TThread)  
  64.   private  
  65.     { Private declarations }  
  66.     FLabel:TLabel;  
  67.     str:String;  
  68.     procedure Show;  
  69.   protected  
  70.     procedure Execute; override;  
  71.   public  
  72.     Constructor Create(aLabel:TLabel);  
  73.   end;  
  74.    
  75. implementation  
  76.    
  77. uses Unit2;  
  78.    
  79. { TMyThread }  
  80.    
  81. procedure TMyThread.Show;  
  82. begin  
  83.   FLabel.Caption:=str;  
  84. end;  
  85.    
  86. Constructor TMyThread.Create(aLabel: TLabel);  
  87. begin  
  88.   FLabel:=aLabel;  
  89.   Inherited Create(False);  
  90. end;  
  91.    
  92. procedure TMyThread.Execute;  
  93. var  
  94.   i:Integer;  
  95. begin  
  96.   { Place thread code here }  
  97.   FreeOnTerminate:=True;  
  98.   if WaitForSingleObject(hSem,INFINITE)=WAIT_OBJECT_0 then  
  99.   begin  
  100.    try  
  101.     for i := 0 to 2000 do  
  102.       begin  
  103.         if not Terminated then  
  104.           begin  
  105.             str:=Format('线程ID:%.4d,第%.4d个循环。',[GetCurrentThreadId,i]);  
  106.             Show;  
  107.             //Synchronize(Show);{不能使用,主线程访问线程类变量会卡死}   
  108.           end;  
  109.       end;  
  110.    finally  
  111.     ReleaseSemaphore(hSem,1,nil);  
  112.    end;  
  113.   end;  
  114. end;  
  115.    
  116. end.  

 

 

运行效果如下,

可以看到,每次只能有两个线程同时运行。

posted on 2012-03-06 20:26  孤独的猫  阅读(2996)  评论(0编辑  收藏  举报