Windows下几种不同的方法来实现线程之间的同步!

来源:互联网 发布:国外建模软件排行 编辑:程序博客网 时间:2024/06/05 02:07

这几天研究了下windows几种同步线程的方法,把自己的理解写出来,附上例子代码供大家一起学习。四种同步线程的方法:1.Mutex(互斥) 2.CriticalSection(临界) 3.Event(事件) 4.Semaphore(信号)

实现目标:两个线程,一个读线程,一个写线程。要达到写一个数到公共缓冲区中,然后触发读线程去读取刚才写入的那个数。读完后通知写线程继续写入,依次循环。达到线程同步操作

开发平台: c++builder

//

//注:HANDLE hRead,hWrite,hMutex,SemaphoreOne,SemaphoreTwo; TCriticalSection *CS;是public

//#define  MUTEX_SYNC
//#define EVENT_SYNC//事件
#define SEMAPHORE//信号                                                                          

///#define CRITICAL_SYNC

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
unsigned char byBuffer[1024] ={0};
unsigned char *lpp = byBuffer;

TEvent *lpReadEvent = new  TEvent(NULL,false,true,"ThreadReadEvent");
TEvent *lpWriteEvent = new  TEvent(NULL,false,true,"ThreadEvent");  //false 自动复位,初始化为有信号态
   
TDateTime BeginTime,EndTime;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
DWORD WINAPI ReadThread(void *lp)
{
      #ifdef MUTEX_SYNC
      for (int i=0;i<256;i++)
      {
          if (WaitForSingleObject(Form1->hMutex,INFINITE) == wrSignaled)//拥有互斥权
          {
             Form1->ListBox1->Items->Add("Read: " + IntToStr(i));//byBuffer[i]
             Form1->ListBox1->ItemIndex = Form1->ListBox1->Items->IndexOf("Read: " + IntToStr(byBuffer[i]));
             Sleep(0);
             ReleaseMutex(Form1->hMutex);
          }

      }

    #elif defined(CRITICAL_SYNC)
      for (int i=0;i<256;i++)
      {
         Form1->CS->Enter();
         Form1->ListBox1->Items->Add("Read: " + IntToStr(i));//byBuffer[i]
         Form1->ListBox1->ItemIndex = Form1->ListBox1->Items->IndexOf("Read: " + IntToStr(byBuffer[i])); 

         Sleep(0);
         Form1->CS->Leave();
        
      }
      #elif defined(SEMAPHORE)
      for (int i=0;i<256;i++)
      {
         WaitForSingleObject(Form1->SemaphoreTwo,INFINITE);
         Form1->ListBox1->Items->Add("Read: " + IntToStr(byBuffer[i]));
         Form1->ListBox1->ItemIndex = Form1->ListBox1->Items->IndexOf("Read: " + IntToStr(byBuffer[i]));
         ReleaseSemaphore(Form1->SemaphoreO,1,NULL);
      }
      #elif  defined(EVENT_SYNC)
      for (int i=0;i<256;i++)
     {
        if (wrSignaled == lpReadEvent->WaitFor(INFINITE))
        {
          Form1->ListBox1->Items->Add("Read: " + IntToStr(byBuffer[i])); //(byBuffer[i]
          Form1->ListBox1->ItemIndex = Form1->ListBox1->Items->IndexOf("Read: " + IntToStr(byBuffer[i]));
          lpEvent->SetEvent();
        }
     }
      #else
      for (int i=0;i<256;i++)
      {
          Form1->ListBox1->Items->Add("Read: " + IntToStr(i));//byBuffer[i]
          Form1->ListBox1->ItemIndex = Form1->ListBox1->Items->IndexOf("Read: " + IntToStr(byBuffer[i]));
      }
      #endif
     EndTime = TDateTime::CurrentTime();
     Form1->Edit3->Text = TimeToStr(EndTime-BeginTime);

   return 0;
}
//---------------------------------------------------------------------------
DWORD WINAPI WriteThread(void *lp)
{
      #ifdef MUTEX_SYNC
      for(int i=0;i<256;i++)
      {
         if (WaitForSingleObject(Form1->hMutex,INFINITE) == wrSignaled)
         {
            byBuffer[i] = i;
            Form1->ListBox1->Items->Add("Write: "+ IntToStr(byBuffer[i]));
            Form1->ListBox1->ItemIndex = Form1->ListBox1->Items->IndexOf("Write: "+ IntToStr(byBuffer[i]));
            Sleep(0);
            ReleaseMutex(Form1->hMutex);
         }
       }

     #elif defined(CRITICAL_SYNC)
       for(int i=0;i<256;i++)
      {
          Form1->CS->Enter();
          byBuffer[i] = i;
          Form1->ListBox1->Items->Add("Write: "+ IntToStr(byBuffer[i]));
          Form1->ListBox1->ItemIndex = Form1->ListBox1->Items->IndexOf("Write: "+ IntToStr(byBuffer[i]));

          Sleep(0);
          Form1->CS->Leave();
      }
      #elif defined(SEMAPHORE)
       for(int i=0;i<256;i++)
       {
          WaitForSingleObject(Form1->Allo,INFINITE);
          byBuffer[i] = i;
          Form1->ListBox1->Items->Add("Write: "+ IntToStr(byBuffer[i]));
          Form1->ListBox1->ItemIndex = Form1->ListBox1->Items->IndexOf("Write: "+ IntToStr(byBuffer[i]));
          ReleaseSemaphore(Form1->Trac,1,NULL);
       }
      #elif  defined(EVENT_SYNC)
      for(int i=0;i<256;i++)
      {
          if (wrSignaled == lpEvent->WaitFor(INFINITE))
          {
             byBuffer[i] = i;
             Form1->ListBox1->Items->Add("Write: "+ IntToStr(byBuffer[i]));
             Form1->ListBox1->ItemIndex = Form1->ListBox1->Items->IndexOf("Write: "+ IntToStr(byBuffer[i]));
             lpReadEvent->SetEvent();
          }
      }
      #else
       for(int i=0;i<256;i++)
       {
          byBuffer[i] = i;
          Form1->ListBox1->Items->Add("Write: "+ IntToStr(byBuffer[i]));//
          Form1->ListBox1->ItemIndex = Form1->ListBox1->Items->IndexOf("Write: "+ IntToStr(byBuffer[i]));
       }
      #endif

     return 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
     unsigned long tReadThread,tWriteThread;

     BeginTime = TDateTime::CurrentTime();
     Form1->Edit2->Text = TimeToStr(BeginTime);

     #ifdef  MUTEX_SYNC
       Label1->Caption = "Current Thread: MUTEX_SYNC";

     #elif defined(CRITICAL_SYNC)
       Label1->Caption = "Current Thread: CRITICAL_SYNC";
      #elif defined(EVENT_SYNC)
       Label1->Caption = "Current Thread: EVENT_SYNC";
     #elif defined(SEMAPHORE)
       Label1->Caption = "Current Thread: SEMAPHORE";
     #else
       Label1->Caption = "Current Thread: NO SYNC";
     #endif

     CS = new TCriticalSection();

     hMutex    = CreateMutex(NULL,false,"ABC");
    
     hWrite = CreateThread(NULL,
                          0,
                          WriteThread,
                          (void*)1,
                          0,
                          &tWriteThread);
     hRead = CreateThread(NULL,
                          0,
                          ReadThread,
                          (void*)1,
                          0,
                          &tReadThread);


      SemaphoreOne = CreateSemaphore(NULL,1,1,"Allo"); //1 默认开始拥有信号量 ,第二值是代表最大值
     SemaphoreTwo  = CreateSemaphore(NULL,0,1,"Trac"); //0 默认开始不拥有信号量
}
通过这个例子分析这几种同步线程的方法,感觉比较好的是用Event或者是信号。Event比较简单。通过这个小例子大家可以试着更好的理解线程的同步操作。

原创粉丝点击