最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++中線程同步與互斥的四種方式介紹及對(duì)比詳解

 更新時(shí)間:2025年01月14日 10:06:26   作者:碼事漫談  
在C++中,當(dāng)兩個(gè)或更多的線程需要訪問(wèn)共享數(shù)據(jù)時(shí),就會(huì)出現(xiàn)線程安全問(wèn)題,這是因?yàn)?如果沒(méi)有適當(dāng)?shù)耐綑C(jī)制,一個(gè)線程可能在另一個(gè)線程還沒(méi)有完成對(duì)數(shù)據(jù)的修改就開始訪問(wèn)數(shù)據(jù),這將導(dǎo)致數(shù)據(jù)的不一致性和程序的不可預(yù)測(cè)性,本文介紹了C++中線程同步與互斥的四種方式介紹及對(duì)比

引言

在C++中,當(dāng)兩個(gè)或更多的線程需要訪問(wèn)共享數(shù)據(jù)時(shí),就會(huì)出現(xiàn)線程安全問(wèn)題。這是因?yàn)?,如果沒(méi)有適當(dāng)?shù)耐綑C(jī)制,一個(gè)線程可能在另一個(gè)線程還沒(méi)有完成對(duì)數(shù)據(jù)的修改就開始訪問(wèn)數(shù)據(jù),這將導(dǎo)致數(shù)據(jù)的不一致性和程序的不可預(yù)測(cè)性。為了解決這個(gè)問(wèn)題,C++提供了多種線程同步和互斥的機(jī)制。

1. 互斥量(Mutex)

互斥量是一種同步機(jī)制,用于防止多個(gè)線程同時(shí)訪問(wèn)共享資源。在C++中,可以使用std::mutex類來(lái)創(chuàng)建互斥量。

#include <thread>
#include <mutex>

std::mutex mtx;  // 全局互斥量
int shared_data = 0;  // 共享數(shù)據(jù)

void thread_func() {
    for (int i = 0; i < 10000; ++i) {
        mtx.lock();  // 獲取互斥量的所有權(quán)
        ++shared_data;  // 修改共享數(shù)據(jù)
        mtx.unlock();  // 釋放互斥量的所有權(quán)
    }
}

int main() {
    std::thread t1(thread_func);
    std::thread t2(thread_func);

    t1.join();
    t2.join();

    std::cout << shared_data << std::endl;  // 輸出20000

    return 0;
}

在上述代碼中,我們創(chuàng)建了一個(gè)全局互斥量mtx和一個(gè)共享數(shù)據(jù)shared_data。然后,我們?cè)趖hread_func函數(shù)中使用mtx.lock()和mtx.unlock()來(lái)保護(hù)對(duì)shared_data的訪問(wèn),確保在任何時(shí)候只有一個(gè)線程可以修改shared_data。

2. 鎖(Lock)

除了直接使用互斥量,C++還提供了std::lock_guard和std::unique_lock兩種鎖,用于自動(dòng)管理互斥量的所有權(quán)。

#include <thread>
#include <mutex>

std::mutex mtx;  // 全局互斥量
int shared_data = 0;  // 共享數(shù)據(jù)

void thread_func() {
    for (int i = 0; i < 10000; ++i) {
        std::lock_guard<std::mutex> lock(mtx);  // 創(chuàng)建鎖,自動(dòng)獲取互斥量的所有權(quán)
        ++shared_data;  // 修改共享數(shù)據(jù)
        // 鎖在離開作用域時(shí)自動(dòng)釋放互斥量的所有權(quán)
    }
}

int main() {
    std::thread t1(thread_func);
    std::thread t2(thread_func);

    t1.join();
    t2.join();

    std::cout << shared_data << std::endl;  // 輸出20000

    return 0;
}

在上述代碼中,我們使用std::lock_guard來(lái)自動(dòng)管理互斥量的所有權(quán)。當(dāng)創(chuàng)建std::lock_guard對(duì)象時(shí),它會(huì)自動(dòng)獲取互斥量的所有權(quán),當(dāng)std::lock_guard對(duì)象離開作用域時(shí),它會(huì)自動(dòng)釋放互斥量的所有權(quán)。這樣,我們就不需要手動(dòng)調(diào)用mtx.lock()和mtx.unlock(),可以避免因忘記釋放互斥量而導(dǎo)致的死鎖。

3. 條件變量(Condition Variable)

條件變量是一種同步機(jī)制,用于在多個(gè)線程之間同步條件的變化。在C++中,可以使用std::condition_variable類來(lái)創(chuàng)建條件變量。

#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;  // 全局互斥量
std::condition_variable cv;  // 全局條件變量
bool ready = false;  // 共享?xiàng)l件

void print_id(int id) {
    std::unique_lock<std::mutex> lock(mtx);  // 創(chuàng)建鎖,自動(dòng)獲取互斥量的所有權(quán)
    while (!ready) {  // 如果條件不滿足
        cv.wait(lock);  // 等待條件變量的通知
    }
    // 當(dāng)收到條件變量的通知,且條件滿足時(shí),繼續(xù)執(zhí)行
    std::cout << "thread " << id << '\n';
}

void go() {
    std::unique_lock<std::mutex> lock(mtx);  // 創(chuàng)建鎖,自動(dòng)獲取互斥量的所有權(quán)
    ready = true;  // 修改共享?xiàng)l件
    cv.notify_all();  // 通知所有等待的線程
}

int main() {
    std::thread threads[10];
    for (int i = 0; i < 10; ++i)
        threads[i] = std::thread(print_id, i);

    std::cout << "10 threads ready to race...\n";
    go();  // 開始比賽

    for (auto& th : threads) th.join();

    return 0;
}

在上述代碼中,我們創(chuàng)建了一個(gè)全局互斥量mtx、一個(gè)全局條件變量cv和一個(gè)共享?xiàng)l件ready。然后,我們?cè)趐rint_id函數(shù)中使用cv.wait(lock)來(lái)等待條件變量的通知,當(dāng)收到條件變量的通知,且條件滿足時(shí),繼續(xù)執(zhí)行。在go函數(shù)中,我們修改共享?xiàng)l件,并使用cv.notify_all()來(lái)通知所有等待的線程。

4. 原子操作(Atomic Operation)

原子操作是一種特殊的操作,它可以在多線程環(huán)境中安全地對(duì)數(shù)據(jù)進(jìn)行讀寫,而無(wú)需使用互斥量或鎖。在C++中,可以使用std::atomic模板類來(lái)創(chuàng)建原子類型。

#include <thread>
#include <atomic>

std::atomic<int> shared_data(0);  // 共享數(shù)據(jù)

void thread_func() {
    for (int i = 0; i < 10000; ++i) {
        ++shared_data;  // 原子操作
    }
}

int main() {
    std::thread t1(thread_func);
    std::thread t2(thread_func);

    t1.join();
    t2.join();

    std::cout << shared_data << std::endl;  // 輸出20000

    return 0;
}

在上述代碼中,我們創(chuàng)建了一個(gè)原子類型的共享數(shù)據(jù)shared_data。然后,我們?cè)?code>thread_func函數(shù)中使用++shared_data來(lái)進(jìn)行原子操作,這樣,我們就不需要使用互斥量或鎖,也可以保證在任何時(shí)候只有一個(gè)線程可以修改shared_data。

5. 對(duì)比

策略優(yōu)點(diǎn)缺點(diǎn)
單一全局互斥量簡(jiǎn)單可能導(dǎo)致嚴(yán)重的性能問(wèn)題,降低并發(fā)性
多個(gè)互斥量提高并發(fā)性增加程序復(fù)雜性,需要避免死鎖
原子操作提高并發(fā)性,避免互斥量開銷增加程序復(fù)雜性,需要理解和使用原子操作
讀寫鎖提高并發(fā)性,特別是讀操作多于寫操作時(shí)增加程序復(fù)雜性,需要管理讀寫鎖,需要避免死鎖

案例舉例

假設(shè)我們正在開發(fā)一個(gè)在線聊天 服務(wù)器,需要處理大量的并發(fā)連接。每個(gè)連接都有一個(gè)關(guān)聯(lián)的用戶對(duì)象,用戶對(duì)象包含了用戶的狀態(tài)信息,如用戶名、在線狀態(tài)等。

在這種情況下,我們可以使用多個(gè)互斥量的策略。我們可以將用戶對(duì)象劃分為幾個(gè)組,每個(gè)組有一個(gè)關(guān)聯(lián)的互斥量。當(dāng)一個(gè)線程需要訪問(wèn)一個(gè)用戶對(duì)象時(shí),它只需要鎖定該用戶對(duì)象所在組的互斥量,而不是所有的用戶對(duì)象。這樣,不同的線程可以同時(shí)訪問(wèn)不同的用戶對(duì)象,從而提高并發(fā)性。

同時(shí),我們也可以使用讀寫鎖的策略。因?yàn)樵诖蠖鄶?shù)情況下,線程只需要讀取用戶的狀態(tài)信息,而不需要修改。所以,我們可以使用讀寫鎖,允許多個(gè)線程同時(shí)讀取用戶對(duì)象,但在修改用戶對(duì)象時(shí)需要獨(dú)占鎖。

在實(shí)踐中,我們可能需要結(jié)合使用這兩種策略,以達(dá)到最佳的效果。

6. 更進(jìn)一步:原子操作+鎖

原子操作和鎖是兩種不同的線程同步機(jī)制,它們可以單獨(dú)使用,也可以一起使用,具體取決于你的應(yīng)用場(chǎng)景。

原子操作是一種低級(jí)的同步機(jī)制,它可以保證對(duì)單個(gè)內(nèi)存位置的讀寫操作是原子的,即在任何時(shí)候只有一個(gè)線程可以對(duì)內(nèi)存位置進(jìn)行操作。原子操作通常用于實(shí)現(xiàn)高級(jí)的同步機(jī)制,如鎖和條件變量。

鎖是一種高級(jí)的同步機(jī)制,它可以保證對(duì)一段代碼或多個(gè)內(nèi)存位置的訪問(wèn)是原子的,即在任何時(shí)候只有一個(gè)線程可以執(zhí)行被鎖保護(hù)的代碼或訪問(wèn)被鎖保護(hù)的內(nèi)存位置。

如果你在使用鎖的同時(shí)還使用原子操作,那么你需要確保你的代碼正確地理解和使用這兩種同步機(jī)制。例如,如果你在一個(gè)被鎖保護(hù)的代碼段中使用原子操作,那么你需要確保原子操作不會(huì)違反鎖的語(yǔ)義,即在任何時(shí)候只有一個(gè)線程可以執(zhí)行被鎖保護(hù)的代碼。

以下是一個(gè)使用原子操作和鎖的例子:

#include <thread>
#include <mutex>
#include <atomic>

std::mutex mtx;  // 全局互斥量
std::atomic<int> counter(0);  // 原子計(jì)數(shù)器

void thread_func() {
    for (int i = 0; i < 10000; ++i) {
        std::lock_guard<std::mutex> lock(mtx);  // 獲取互斥量的所有權(quán)
        ++counter;  // 原子操作
        // 鎖在離開作用域時(shí)自動(dòng)釋放互斥量的所有權(quán)
    }
}

int main() {
    std::thread t1(thread_func);
    std::thread t2(thread_func);

    t1.join();
    t2.join();

    std::cout << counter << std::endl;  // 輸出20000

    return 0;
}

在上述代碼中,我們使用std::lock_guard來(lái)獲取互斥量的所有權(quán),然后使用++counter來(lái)進(jìn)行原子操作。這樣,我們既保證了在任何時(shí)候只有一個(gè)線程可以執(zhí)行被鎖保護(hù)的代碼,也保證了對(duì)counter的操作是原子的。

總的來(lái)說(shuō),原子操作和鎖可以一起使用,但你需要確保你的代碼正確地理解和使用這兩種同步機(jī)制。

總結(jié)

在C++中,當(dāng)兩個(gè)或更多的線程需要訪問(wèn)共享數(shù)據(jù)時(shí),可以使用互斥量、鎖、條件變量和原子操作等多種線程同步和互斥的機(jī)制來(lái)保證線程安全。選擇哪種機(jī)制,取決于具體的應(yīng)用場(chǎng)景和需求。

以上就是C++中線程同步與互斥的四種方式介紹及對(duì)比詳解的詳細(xì)內(nèi)容,更多關(guān)于C++線程同步與互斥方式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

广东省| 满洲里市| 白朗县| 吉木萨尔县| 高邑县| 喀喇沁旗| 甘孜县| 田阳县| 洪泽县| 潼关县| 临澧县| 耒阳市| 湖州市| 利川市| 铁力市| 锦州市| 克什克腾旗| 定边县| 沧州市| 宜城市| 屏南县| 鄯善县| 武威市| 克拉玛依市| 赣榆县| 万盛区| 平陆县| 庐江县| 柳州市| 甘肃省| 芒康县| 九龙县| 沈阳市| 广东省| 榆社县| 万安县| 嵊泗县| 沈丘县| 马公市| 新沂市| 灌阳县|