C++ 并发编程(一):创建线程

C++ 并发编程(一):创建线程

这个系列是我近期学习 C++ 并发编程的总结,文章和代码最初都是基于 Boost.Thread,但是最近越来越发现,STL 内置的线程和同步工具已经足够完善了。

STL 和 Boost 线程,在设计和用法上极其相似,一旦掌握了一个,不难切换到另一个。如果非要比较的话,Boost 更完善一些,比如 Boost 提供了 thread_group 和 upgrade_lock,STL 则没有。

此节介绍「线程的创建」。

Hello 1
通过一个不带参数的函数创建线程。

#include <iostream>
#include <thread>

void hello()
{
    // 睡眠一秒以模拟数据处理。
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "hello, world!" << std::endl;
}

int main(int argc, char *argv[])
{
    // 创建一个线程对象,注意函数 hello 将立即运行。
    // hello 和 &hello的值相等,均代表函数地址
    std::thread t(hello);
    //std::thread t(&hello);

    // 等待线程结束。
    // 否则线程还没执行(完),主程序就已经结束了。
    // 注:还没执行是一种状态,没执行完也是一种状态
    t.join();
    return 0;
}

输出结果为:

hello, world!

Hello 2
通过一个带参数的函数创建线程。

#include <iostream>
#include <thread>

void hello(const char *what)
{
    // 睡眠一秒以模拟数据处理。
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "hello, " << what << "!" << std::endl;
}

int main(int argc, char *argv[])
{
    std::thread t1(hello, "world");
    t1.join();
    std::thread t2(&hello, "world");
    t2.join();
    // 等价于使用 bind:
    std::thread t3(std::bind(hello, "world"));
    t3.join();
    std::thread t4(std::bind(&hello, "world"));
    t4.join();

    return 0;
}

输出结果为:

hello, world!
hello, world!
hello, world!
hello, world!

Hello 3
通过一个函数对象——即仿函数(functor)——创建线程。

#include <iostream>
#include <thread>

class Hello {
public:
    void operator()(const char *what) {
        // 睡眠一秒以模拟数据处理。
        std::this_thread::sleep_for(std::chrono::seconds(1));
        std::cout << "hello, " << what << "!" << std::endl;
    }
};

int main(int argc, char *argv[])
{
    Hello hello;
    // 方式一:拷贝函数对象。
    std::thread t1(hello, "world");
    t1.join();

    // 方式二:不拷贝函数对象,通过 std::ref 传入引用。
    // 用户必须保证被线程引用的函数对象,拥有超出线程的生命期。
    // 比如这里通过 join 线程保证了这一点。
    std::thread t2(std::ref(hello), "world");
    t2.join();

    // 方式三:不拷贝函数对象,通过 std::move
    std::thread t3(std::move(hello), "world");
    t3.join();

    hello("world");

    return 0;
}

输出结果为:

hello, world!
hello, world!
hello, world!
hello, world!

Hello 4
通过一个成员函数创建线程。
与前例不同之处在于,需要以 bind 绑定 this 指针作为第一个参数。

#include <iostream>
#include <thread>

class Hello {
public:
    Hello() {
        std::thread t1(std::bind(&Hello::entry, this, "world"));
        t1.join();
        std::thread t2(&Hello::entry, this, "world");
        t2.join();
    }

private:
    // 线程函数
    void entry(const char *what) {
        // 睡眠一秒以模拟数据处理。
        std::this_thread::sleep_for(std::chrono::seconds(1));
        std::cout << "hello, " << what << "!" << std::endl;
    }
};

int main(int argc, char *argv[])
{
    Hello hello;
    return 0;
}

Counter
创建两个线程,各自倒着计数。
此例顺带演示了 detached 线程,被 detached 的线程,自生自灭,不受控制,无法再 join。

#include <iostream>
#include <thread>

class Counter
{
public:
    Counter(int value) : value_(value) {

    }
    void operator()() {
        while (value_ > 0) {
            std::cout << value_ << " ";
            --value_;
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
        std::cout << std::endl;
    }
private:
    int value_;
};

int main() {
    std::thread t1(Counter(3));
    t1.join();

    std::thread t2(Counter(3));
    t2.detach();

    // 等待几秒,不然 t2 根本没机会执行。
    std::this_thread::sleep_for(std::chrono::seconds(4));

    return 0;
}

输出结果为:

3 2 1 
3 2 1 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值