首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++/CLI 多執行緒程式設計實戰解析:從基礎概念到同步機制

     編輯:關於C++

前言:執行緒與多任務處理核心觀念

從處理器角度來看,執行緒是獨立的執行流程,各自擁有暫存器與堆疊上下文。在單核心處理器環境下,執行環境在一個時間片段內只能執行一個執行緒。當執行緒無法取得所需資源(如 I/O 作業)或用完時間片時,會發生「上下文切換」。當某執行緒進入「阻塞」狀態而系統切換執行其他執行緒時,有效減少處理器閒置時間,這就是「多任務」的運作原理。

進程與執行緒的關係

程式執行時,系統會分配包含虛擬記憶體的位址空間,這個運行時上下文稱為「進程」。每個進程至少擁有一個執行緒——「主執行緒」,它與後續建立的執行緒本質上沒有差異,只是碰巧是第一個建立的。進程內的執行緒數量在運行時可動態變化,任何執行緒都能建立新執行緒,但所有執行緒皆屬於同一進程整體,共享相同位址空間與資源。當進程內最後一個執行緒結束時,父進程也隨之終止。

為何需要多執行緒?

若進程只有一個執行緒,執行流程將自上而下循序執行;當執行緒阻塞且無其他活躍執行緒時,系統進入閒置狀態,造成大量等待時間浪費。實際應用中,進程通常包含多個可並行的「子任務」。例如列印假脫機程式:一個執行緒負責傳送列印工作到印表機,另一個處理用戶新請求,兩者獨立運作,避免輪詢機制的時間浪費與延遲權衡難題。

關鍵概念:原子性與可重入性

原子性:原子變數或物件作為整體被存取,甚至在非同步操作下也能保證邏輯完整性——要麼讀到舊值,要麼讀到新值,不會出現新舊值混雜。C++/CLI 大多數基本型別具備原子性,但複雜物件(如 Point 結構、陣列)不具備,需透過同步機制保護。

可重入性:可重入函數可被多執行緒安全平行執行。各執行緒在函數內分配的資料(來自堆疊或堆積)彼此獨立。但若函數存取執行緒間共享的變數或檔案,仍需同步方法。

建立執行緒實戰範例

以下範例展示主執行緒建立兩個子執行緒並行執行,無共享資料、無同步機制:

using namespace System;
using namespace System::Threading;

public ref class ThreadX
{
    int loopStart, loopEnd, dispFrequency;
public:
    ThreadX(int start, int end, int freq) 
        : loopStart(start), loopEnd(end), dispFrequency(freq) {}
    
    void ThreadEntryPoint()
    {
        String^ name = Thread::CurrentThread->Name;
        for (int i = loopStart; i <= loopEnd; ++i)
            if (i % dispFrequency == 0)
                Console::WriteLine("{0}: i = {1,10}", name, i);
        Console::WriteLine("{0} thread terminating", name);
    }
};

int main()
{
    ThreadX^ o1 = gcnew ThreadX(0, 1000000, 200000);
    Thread^ t1 = gcnew Thread(gcnew ThreadStart(o1, &ThreadX::ThreadEntryPoint));
    t1->Name = "t1";

    ThreadX^ o2 = gcnew ThreadX(-1000000, 0, 200000);
    Thread^ t2 = gcnew Thread(gcnew ThreadStart(o2, &ThreadX::ThreadEntryPoint));
    t2->Name = "t2";

    t1->Start();
    t2->Start();
    Console::WriteLine("Primary thread terminating");
}

執行緒物件建構後處於未啟用狀態,需呼叫 Start() 才真正建立新執行流程。輸出結果顯示三個執行緒輸出交織穿插,主執行緒可能先於子執行緒結束,證明執行緒生命週期獨立於建立關係。

同步機制:Monitor 類別與同步鎖

當多執行緒存取共享資源時,必須使用同步機制。C++/CLI 為每個物件提供同步鎖,透過 Monitor::Enter 與 Monitor::Exit 實現獨佔存取:

void Move(int xor, int yor)
{
    Monitor::Enter(this);
    X = xor; Y = yor;
    Monitor::Exit(this);
}

同步鎖保證同一時間只有一個實例函數在物件上執行關鍵程式碼。鎖的作用範圍應盡可能縮小,避免不必要阻塞。釋放鎖時需注意異常處理,建議使用 try/finally 確保 Monitor::Exit 必被呼叫。

靜態類別同步與專用鎖物件

靜態函數同步可使用 typeid 操作符或專用靜態 Object^ Lock 物件:

static Object^ Lock = gcnew Object;
static void F3() { Monitor::Enter(Lock); /*...*/ Monitor::Exit(Lock); }
static void F4() { Monitor::Enter(Lock); /*...*/ Monitor::Exit(Lock); }

巢狀同步鎖會增加鎖計數,必須遞減至零才能被其他執行緒存取。不同物件的同步鎖可巢狀包含,但會阻塞直到內層物件可存取。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved