程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++多線程編程簡略實例

C++多線程編程簡略實例

編輯:關於C++

C++多線程編程簡略實例。本站提示廣大學習愛好者:(C++多線程編程簡略實例)文章只能為提供參考,不一定能成為您想要的結果。以下是C++多線程編程簡略實例正文


C++自己並沒有供給任何多線程機制,然則在windows下,我們可以挪用SDK win32 api來編寫多線程的法式,上面就此簡略的講一下:

創立線程的函數


HANDLE CreateThread(
    LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
    SIZE_T dwStackSize,                       // initial stack size
    LPTHREAD_START_ROUTINE lpStartAddress,    // thread function
    LPVOID lpParameter,                       // thread argument
    DWORD dwCreationFlags,                    // creation option
    LPDWORD lpThreadId                        // thread identifier
);

在這裡我們只用到了第三個和第四個參數,第三個參數傳遞了一個函數的地址,也是我們要指定的新的線程,第四個參數是傳給新線程的參數指針。

eg1:


#include <iostream>
#include <windows.h>
using namespace std;
DWORD WINAPI Fun(LPVOID lpParamter)
{
      while(1) { cout<<"Fun display!"<<endl; }
}
int main()
{
    HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);
    CloseHandle(hThread);
    while(1) { cout<<"main display!"<<endl;  }
    return 0;
}

我們可以看到主線程(main函數)和我們本身的線程(Fun函數)是隨機地瓜代履行的,然則兩個線程輸入太快,使我們很好看清晰,我們可使用函數


VOID Sleep(
    DWORD dwMilliseconds   // sleep time
);

來暫停線程的履行,dwMilliseconds表現千分之一秒,所以

Sleep(1000);

表現暫停1秒

eg2:


#include <iostream>
#include <windows.h>
using namespace std;
DWORD WINAPI Fun(LPVOID lpParamter)
{   
      while(1) { cout<<"Fun display!"<<endl; Sleep(1000);}
}
int main()
{
      HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);
      CloseHandle(hThread);
      while(1) { cout<<"main display!"<<endl;  Sleep(2000);}
      return 0;
}

履行上述代碼,此次我們可以清晰地看到在屏幕上交織地輸入Fun display!和main display!,我們發明這兩個函數確切是並發運轉的,仔細的讀者能夠會發明我們的法式是每當Fun函數和main函數輸入內容後就會輸入換行,然則我們看到切實其實是有的時刻法式輸入換行了,有的時刻確沒有輸入換行,乃至有的時刻是輸入兩個換行。這是怎樣回事?上面我們把法式改一下看看:

eg3:


#include <iostream>
#include <windows.h>
using namespace std;
DWORD WINAPI Fun(LPVOID lpParamter)
{
      while(1) { cout<<"Fun display!\n"; Sleep(1000);}
}
int main()
{
      HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);
      CloseHandle(hThread);
      while(1) { cout<<"main display!\n";  Sleep(2000);}
      return 0;
}

我們再次運轉這個法式,我們發明這時候候正如我們預期的,准確地輸入了我們想要輸入的內容而且格局也是准確的。上面我就來說一下此前我們的法式為何沒有准確的運轉。多線程的法式時並發地運轉的,多個線程之間假如公用了一些資本的話,我們其實不能包管這些資本都能准確地被應用,由於這個時刻資本其實不是獨有的,舉個例子吧:

eg4:

參加有一個資本 int a = 3

有一個線程函數 selfAdd() 該函數是使 a += a;

又有一個線程函數 selfSub() 該函數是使a -= a;

我們假定下面兩個線程正在並發欲行,假如selfAdd在履行的時刻,我們的目標是想讓a編程6,但此時selfSub獲得了運轉的機遇,所以a釀成了0,比及selfAdd的到履行的機遇後,a += a ,然則此時a確是0,並沒有如我們所預期的那樣的到6,我們回到後面EG2,在這裡,我們可以把屏幕算作是一個資本,這個資本被兩個線程所共用,參加當Fun函數輸入了Fun display!後,將要輸入endl(也就是清空緩沖區並換行,在這裡我們可以不消懂得甚麼事緩沖區),但此時main函數確獲得了運轉的機遇,此時Fun函數還沒有來得及輸入換行就把CPU讓給了main函數,而這時候main函數就直接在Fun display!後輸入main display!,至於為何有的時刻法式會持續輸入兩個換行,讀者可以采取異樣的剖析辦法來剖析,在這裡我就不多講了,留給讀者本身思慮了。

那末為何我們把eg2改成eg3便可以准確的運轉呢?緣由在於,多個線程固然是並發運轉的,然則有一些操作是必需趁熱打鐵的,不許可打斷的,所以我們看到eg2和eg3的運轉成果是紛歧樣的。

那末,是否是eg2的代碼我們就弗成以讓它准確的運轉呢?謎底固然能否,上面我就來說一下如何能力讓eg2的代碼可以准確運轉。這觸及到多線程的同步成績。關於一個資本被多個線程共用會招致法式的凌亂,我們的處理辦法是只許可一個線程具有對同享資本的獨有,如許就可以夠處理下面的成績了。


HANDLE CreateMutex(
    LPSECURITY_ATTRIBUTES lpMutexAttributes,  // SD
    BOOL bInitialOwner,                       // initial owner
    LPCTSTR lpName                            // object name
 );

該函數用於發明一個獨有資本,第一個參數我們沒有應用,可以設為NULL,第二個參數指定該資本初始能否歸屬創立它的過程,第三個參數指定資本的稱號。


HANDLE hMutex = CreateMutex(NULL,TRUE,"screen");

這條語句發明了一個名為screen而且歸屬於創立它的過程的資本


BOOL ReleaseMutex(
    HANDLE hMutex   // handle to mutex
  );

該函數用於釋放一個獨有資本,過程一旦釋放該資本,該資本就不再屬於它了,假如還要用到,須要從新請求獲得該資本。請求資本的函數以下


DWORD WaitForSingleObject(
    HANDLE hHandle,        // handle to object
    DWORD dwMilliseconds   // time-out interval
  );

第一個參數指定所請求的資本的句柄,第二個參數普通指定為INFINITE,表現假如沒有請求到資本就一向期待該資本,假如指定為0,表現一旦得不到資本就前往,也能夠詳細地指定期待多久才前往,單元是千分之一秒。好了,該到我們來處理eg2的成績的時刻了,我們可以把eg2做一些修正,以下

eg5:


#include <iostream>
#include <windows.h>
using namespace std;
HANDLE hMutex;
DWORD WINAPI Fun(LPVOID lpParamter)
{
       while(1) {
                 WaitForSingleObject(hMutex, INFINITE);
                 cout<<"Fun display!"<<endl;
                 Sleep(1000);
                 ReleaseMutex(hMutex);
        }
  }
int main()
{
      HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);
      hMutex = CreateMutex(NULL, FALSE, "screen");
      CloseHandle(hThread);
      while(1) {
               WaitForSingleObject(hMutex, INFINITE);
               cout<<"main display!"<<endl; 
               Sleep(2000);
               ReleaseMutex(hMutex);
      }
      return 0;
}

運轉代碼正如我們所預期的輸入的內容。

以上所述就是本文的全體內容了,願望年夜家可以或許愛好。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved