C++11 線程管理

1 線程啟動(dòng)
2 參數(shù)傳遞
  2.1 參數(shù)傳遞
  2.2 引用傳參
3 線程所有權(quán)管理
4 線程標(biāo)志

1 線程啟動(dòng)

std::thread構(gòu)造函數(shù)接受可調(diào)用對(duì)象啟動(dòng)線程壹店,如下所示:

#include <iostream>
#include <thread>
#include <string>
#include <functional>

void f(int i) {
    std::cout << "Func, i=" << i << "\n";
}

struct Foo {
    void operator()(int i) {
        std::cout << "Class Function Call Object, i=" << i << "\n";
    }
};

struct Foo2 {
    void func(int i) {
        std::cout << "Class Method, i=" << i << "\n";
    }
};

int main() {
    // by normal function
    std::thread t1(f, 1);
    t1.join();

    // by class operator()
    Foo foo;
    std::thread t2(foo, 2);
    t2.join();

    //by lamda
    int i = 3;
    std::thread t3([i]() {
        std::cout << "Lamda, i=" << i << "\n";
    });
    t3.join();

    // by member function
    Foo2 foo2;
    auto f3 = std::mem_fn(&Foo2::func);
    std::thread t4(f3, foo2, 4);
    t4.join();

    // by bind
    auto f1 = std::bind(f, std::placeholders::_1);
    std::thread t5(f1, 5);
    t5.join();

    // by std::function
    std::function<void(int)> f2 = f;
    std::thread t6(f2, 6);
    t6.join();
}

假設(shè)文件名為thread.cpp, 則編譯命令為:
g++ -std=c++11 -lpthread thread.cpp -o test_thread
執(zhí)行./test_thread后程序輸出為

Func, i=1
Class Function Call Object, i=2
Lamda, i=3
Class Method, i=4
Func, i=5
Func, i=6

2 參數(shù)傳遞

2.1 基本范例

下面例子是一個(gè)向線程傳遞參數(shù)的示例

#include <iostream>
#include <thread>
#include <string>
void f(int i, const std::string& s) {
    std::cout << "i = " << i << "\n"
        << "s = " << s << std::endl;
}

int main() {
    char buffer[1024];
    sprintf(buffer, "%i", 1234);
    std::thread t(f, 3, buffer);
    t.detach();
}

這個(gè)程序存在一個(gè)隱患, 由于主進(jìn)程detach了师坎,所以buffer在轉(zhuǎn)成std::string之前有可能因?yàn)橹鬟M(jìn)程退出而銷毀耍攘,正確的方式是在主進(jìn)程中就把buffer轉(zhuǎn)成std::string, 如下

// std::thread t(f, 3, buffer);  =>
std::thread t(f, 3, std::string(buffer));

2.2 引用傳參

C++11 支持使用std::ref向線程按照引用方式傳遞參數(shù), 如下范例:

#include <iostream>
#include <thread>
#include <string>

void func(int& i, std::string& s) {
    ++i;
    s = "update value";
}

int main() {
    int i = 0;
    std::string s("old value");
    std::thread t(func, std::ref(i), std::ref(s));
    t.join();

    std::cout << "i=" << i << "\n"
        << "s=" << s << std::endl;
    return 0;
}

程序輸出結(jié)果為:

i=1
s=update value

3 線程所有權(quán)管理

std::thread都是可移動(dòng)榕栏,但不可拷貝, 如下面示例:

#include <iostream>
#include <thread>

void f(int i) {
    std::cout << "Func, i=" << i << "\n";
}

std::thread gen_a_thread() {
    std::thread t(f, 2);
    return t;
}

int main() {
    std::thread t1(f, 1);

    //std::thread t2 = t1;  this is not allowed

    // transfer ownership, call move constructor
    std::thread t2 = std::move(t1);
    t2.join();

    // transfer ownership, call move constructor
    std::thread t3 = gen_a_thread();
    t3.join();
}

輸出為:

Func, i=1
Func, i=2

對(duì)于需要join的線程蕾各,為了確保join一定會(huì)被調(diào)用扒磁,可以創(chuàng)建下面的thread_scope類,如下:

#include <iostream>
#include <thread>
#include <exception>

void f(int i) {
    std::cout << "Func, i=" << i << "\n";
}

class ThreadScope {
public:
    explicit ThreadScope(std::thread t): _t(std::move(t)) {
        if (!_t.joinable()) {
            throw std::logic_error("no thread");
        }
    }

    ~ThreadScope() {
        _t.join();
    }

    //disallow copy and assign
    ThreadScope(const ThreadScope& t) = delete;
    ThreadScope& operator=(const ThreadScope& t) = delete;

private:
    std::thread _t;
};


int main() {
    ThreadScope ts(std::thread(f, 1));
}

可以將std::thread放入std::vector中式曲,批量創(chuàng)建線程并且等待它們結(jié)束妨托,示例如下:

#include <iostream>
#include <thread>
#include <vector>
#include <sstream>
#include <algorithm>

void worker(int i) {
    std::stringstream ss;
    ss << "worker_";
    ss << i;
    ss << "\n";
    std::cout << ss.str();
}

int main() {
    const size_t WORKER_NUM = 20;
    std::vector<std::thread> threads;
    for (auto i = 0; i < WORKER_NUM; ++i) {
        threads.emplace_back(std::thread(worker, i));
    }

    std::for_each(threads.begin(), threads.end(), std::mem_fn(&std::thread::join));
}

4 線程標(biāo)志

線程標(biāo)識(shí)類型是std::thread::id,可以通過(guò)兩種方式進(jìn)行檢索吝羞。第一種兰伤,可以通過(guò)調(diào)用std::thread對(duì)象的成員函數(shù)get_id()來(lái)直接獲取。如果std::thread對(duì)象沒有與任何執(zhí)行線程相關(guān)聯(lián)钧排,get_id()將返回std::thread::type默認(rèn)構(gòu)造值敦腔,這個(gè)值表示“沒有線程”。第二種恨溜,當(dāng)前線程中調(diào)用std::this_thread::get_id()符衔。 示例代碼如下:

#include <iostream>
#include <thread>
#include <vector>
#include <sstream>
#include <algorithm>

void worker(int i) {
    std::stringstream ss;
    ss << std::this_thread::get_id() << "\n";
    std::cout << ss.str();
}

int main() {
    const size_t WORKER_NUM = 5;
    std::vector<std::thread> threads;
    for (auto i = 0; i < WORKER_NUM; ++i) {
        threads.emplace_back(std::thread(worker, i));
    }

    std::for_each(threads.begin(), threads.end(), std::mem_fn(&std::thread::join));
}

輸出如下:

139865582319360
139865571829504
139865561339648
139865540359936
139865550849792
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末找前,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子判族,更是在濱河造成了極大的恐慌纸厉,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件五嫂,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡肯尺,警方通過(guò)查閱死者的電腦和手機(jī)沃缘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)则吟,“玉大人槐臀,你說(shuō)我怎么就攤上這事∶ブ伲” “怎么了水慨?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)敬扛。 經(jīng)常有香客問(wèn)我晰洒,道長(zhǎng),這世上最難降的妖魔是什么啥箭? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任谍珊,我火速辦了婚禮,結(jié)果婚禮上急侥,老公的妹妹穿的比我還像新娘砌滞。我一直安慰自己,他們只是感情好坏怪,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布贝润。 她就那樣靜靜地躺著,像睡著了一般铝宵。 火紅的嫁衣襯著肌膚如雪打掘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天鹏秋,我揣著相機(jī)與錄音胧卤,去河邊找鬼。 笑死拼岳,一個(gè)胖子當(dāng)著我的面吹牛彰居,可吹牛的內(nèi)容都是我干的潘鲫。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼设褐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了霹疫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎压汪,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體古瓤,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡止剖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了落君。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片穿香。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖绎速,靈堂內(nèi)的尸體忽然破棺而出皮获,到底是詐尸還是另有隱情,我是刑警寧澤纹冤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布洒宝,位于F島的核電站,受9級(jí)特大地震影響萌京,放射性物質(zhì)發(fā)生泄漏雁歌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一知残、第九天 我趴在偏房一處隱蔽的房頂上張望将宪。 院中可真熱鬧,春花似錦橡庞、人聲如沸较坛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至吧趣,卻和暖如春法竞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背强挫。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工岔霸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人俯渤。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓呆细,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親八匠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子絮爷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容