日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
解鎖C++并發(fā)編程的鑰匙:探索Atomic變量

最近在用c++搞項(xiàng)目,因?yàn)槎嗑€程要做一個(gè)類似cnt的保護(hù),今天學(xué)習(xí)了c++的原子操作。

成都創(chuàng)新互聯(lián)長(zhǎng)期為上千客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為烏拉特后企業(yè)提供專業(yè)的網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè),烏拉特后網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。

探索c++的原子類型

std::atomic 類型是 C++ 提供的一種機(jī)制,用于實(shí)現(xiàn)多線程之間的安全共享數(shù)據(jù)。它通過(guò)原子操作來(lái)確保對(duì)共享變量的操作是不可分割的。在多線程環(huán)境下,如果沒(méi)有適當(dāng)?shù)耐綑C(jī)制,對(duì)共享變量的讀寫(xiě)可能會(huì)導(dǎo)致競(jìng)爭(zhēng)條件,進(jìn)而引發(fā)不確定的行為。std::atomic 類型提供了一種解決方案,讓我們能夠以線程安全的方式訪問(wèn)這些變量。

關(guān)于具體的函數(shù)和詳細(xì)介紹可以訪問(wèn)這里:https://cplusplus.com/reference/atomic/atomic/?kw=atomic

這里介紹幾個(gè)常用的:

  • load 和 store:用于讀取和寫(xiě)入原子變量的值。
  • exchange:交換原子變量的值,并返回之前的值。
  • compare_exchange_strong 和 compare_exchange_weak:比較并交換操作,可在特定條件下修改原子變量的值。
  • fetch_add 和 fetch_sub:原子地執(zhí)行加法和減法操作,并返回之前的值。

這里原子操作后為什么要返回之前的值呢?

以fetch_add為例,fetch_add是用于對(duì)原子變量進(jìn)行原子性地增加操作。它執(zhí)行一個(gè)原子的加法操作,并返回加法操作之前的原子變量的值。

這種設(shè)計(jì)是基于并發(fā)編程中的常見(jiàn)需求。返回之前的值允許程序員在執(zhí)行加法操作后,獲取加法之前的原始值。這樣做有以下幾個(gè)方面的優(yōu)點(diǎn):

  • 原子性操作的完整性:在多線程并發(fā)環(huán)境下,如果需要進(jìn)行原子性的加法操作,同時(shí)又需要獲取加法前的值,fetch_add 的設(shè)計(jì)能夠保證這兩個(gè)操作的原子性。它在單個(gè)原子操作中完成增加操作,并返回增加前的值,避免了在多線程環(huán)境下的競(jìng)態(tài)條件。
  • 避免競(jìng)態(tài)條件:返回之前的值可以讓程序員在進(jìn)行加法操作之后,檢查原子變量的舊值,并根據(jù)舊值進(jìn)行后續(xù)的操作。這對(duì)于實(shí)現(xiàn)一些特定的同步模式或算法是非常有用的,因?yàn)樗苊饬艘驗(yàn)椴僮鏖g的競(jìng)爭(zhēng)導(dǎo)致的意外結(jié)果。

舉個(gè)栗子

這里做一個(gè)簡(jiǎn)單的線程池,并實(shí)現(xiàn)一個(gè)task,task的任務(wù)就是對(duì)原子變量counter進(jìn)行遞增,最后我們看結(jié)果是否與預(yù)期一致,這里線程池實(shí)現(xiàn)10個(gè)線程,給線程池推送100000個(gè)task。

#include 
#include 
#include 
#include 
#include 
#include 
#include 

class ThreadPool {
public:
    ThreadPool(size_t numThreads) : stop(false) {
        for (size_t i = 0; i < numThreads; ++i) {
            threads.emplace_back([this] {
                while (true) {
                    std::function task;
                    {
                        std::unique_lock lock(queueMutex);
                        condition.wait(lock, [this] { return stop || !tasks.empty(); });
                        if (stop && tasks.empty()) {
                            return;
                        }
                        task = std::move(tasks.front());
                        tasks.pop();
                    }
                    task();
                }
            });
        }
    }

    template 
    void AddTask(F&& f) {
        {
            std::lock_guard lock(queueMutex);
            tasks.emplace(std::forward(f));
        }
        condition.notify_one();
    }

    ~ThreadPool() {
        {
            std::lock_guard lock(queueMutex);
            stop = true;
        }
        condition.notify_all();
        for (std::thread& worker : threads) {
            worker.join();
        }
    }

private:
    std::vector threads;
    std::queue> tasks;
    std::mutex queueMutex;
    std::condition_variable condition;
    bool stop;
};

int main() {
    std::atomic counter(0);
    ThreadPool pool(10);

    constexpr int numTasks = 100000;
    for (int i = 0; i < numTasks; ++i) {
        pool.AddTask([&counter]() {
            counter++;
        });
    }

    std::cout << "Waiting for tasks to complete..." << std::endl;

    //注意:這里不會(huì)確保所有任務(wù)已經(jīng)執(zhí)行完畢,僅僅是等待一段時(shí)間以展示結(jié)果
    std::this_thread::sleep_for(std::chrono::seconds(5));

    std::cout << "Final Counter Value: " << counter << std::endl;

    return 0;
}

我們預(yù)期最后的結(jié)果是100000。g++編譯,不要忘記加-lpthread,執(zhí)行:

細(xì)心的小伙伴可能發(fā)現(xiàn)我的代碼直接使用的counter++,這里需要注意,這只是個(gè)簡(jiǎn)單的測(cè)試代碼,實(shí)際項(xiàng)目中要最好使用counter.fetch_add(1),因?yàn)閏ounter++不保證++是個(gè)原子操作。我在項(xiàng)目中遇到了該問(wèn)題,最后加出來(lái)總會(huì)比預(yù)期值少,后來(lái)?yè)Q成fetch_add后就正常了。


分享文章:解鎖C++并發(fā)編程的鑰匙:探索Atomic變量
網(wǎng)頁(yè)路徑:http://www.dlmjj.cn/article/djiophi.html