C++从入门到放弃C++多线程

C++11 std::thread 学习笔记

2019-03-29  本文已影响0人  lixin_karl

主要方法介绍

template<typename _Callable, typename... _Args>
    explicit thread(_Callable&& __f, _Args&&... __args)  线程创建函数(函数,参数...)
void swap(thread& __t) noexcept  交换线程
bool joinable() const noexcept  判断线程是否可以加入等待
void join()  加入等待,等待这个线程结束。
void detach()  分离线程 设置线程为独立线程。
native_handle_type native_handle()  获得线程句柄
static unsigned int hardware_concurrency() noexcept  返回系统cpu核数
例子
void Run1(int a)
{
    std::cout<<"Run1("<<a<<")"<<std::endl;
}
void Run2(int a,int b)
{
    std::cout<<"Run2("<<a<<","<<b<<")"<<std::endl;
}

int main()
{
    auto t1 = std::thread(Run1,3);
    auto t2 = std::thread(Run2,5,7);
    t1.join();t2.join();
}
输出结果
Run1(3)
Run2(5,7)

join函数是要求等待线程结束后,主线程才能结束,如果调用join函数的话会出现

terminate called whithout an active exception

错误,Google给出的解答是,这由于在停止线程时,导致它脱离了栈的控制,这就意味着你必须使用join 函数 或者 detach函数。

detach例子

void Run1(int a)
{
    std::cout<<"Run1("<<a<<")"<<std::endl;
}
void Run2(int a,int b)
{
    std::cout<<"Run2("<<a<<","<<b<<")"<<std::endl;
}
int main()
{
    auto t1 = std::thread(Run1,3);
    auto t2 = std::thread(Run2,5,7);
    t1.detach();t2.detach();
}
输出结果
Run1(3)

detach函数会导致t1 t2 从主线程分离开来,主线程结束的时候 t2 还未来得及打印数据,导致只出现一条打印数据。

原子变量与线程安全
普通变量
int sum = 0;
int N = 1000000;

void Count()
{
    for(auto i = 0; i <N ; ++i)
    {
        ++sum;
    }
}

int main()
{
    auto start = clock();
    auto t1 = std::thread(Count);
    auto t2 = std::thread(Count);
    t1.join();
    t2.join();
    auto end = clock();
    std::cout<<"Sum = "<<sum<<"消耗时间:"<<end-start<<std::endl;
}
加锁
int sum = 0;
int N = 1000000;
std::mutex m;

void Count()
{
    for(auto i = 0; i <N ; ++i)
    {
        m.lock();
        ++sum;
        m.unlock();
    }
}

int main()
{
    auto start = clock();
    auto t1 = std::thread(Count);
    auto t2 = std::thread(Count);
    t1.join();
    t2.join();
    auto end = clock();
    std::cout<<"Sum = "<<sum<<"消耗时间:"<<end-start<<std::endl;
}
输出结果
Sum = 2000000消耗时间:94
原子变量
int sum = 0;
int N = 1000000;
std::mutex m;
std::atomic_int atomic_sum = 0;
void Count()
{
    for(auto i = 0; i <N ; ++i)
    {
        ++atomic_sum;
    }
}

int main()
{
    auto start = clock();
    auto t1 = std::thread(Count);
    auto t2 = std::thread(Count);
    t1.join();
    t2.join();
    auto end = clock();
    std::cout<<"Sum = "<<atomic_sum<<"消耗时间:"<<end-start<<std::endl;
}
输出结果
Sum = 2000000消耗时间:46

普通变量导致算出的最终结果不是我们所期望的,导致错误;对普通变量加锁后,得到了期望结果;使用原子变量后,效率得到了提升,而且结果正确。

类中使用线程
class Task{
public:
    void Start()
    {
        thread = std::thread([&]{
            this->Run();
        });
    }
    void Join()
    {
        thread.join();
    }
    virtual void Run() = 0;
private:
    std::thread thread;
};
class Task1 : public Task{
    void Run() override
    {
        std::cout<<"I am Job 1"<<std::endl;
    }
};
class Task2 : public Task{
    void Run() override
    {
        std::cout<<"I am Job 2"<<std::endl;
    }
};


int main()
{
    Task1 t1;
    Task2 t2;
    t1.Start();
    t2.Start();
    t1.Join();
    t2.Join();
    return 0;
}
输出结果
I am Job 1
I am Job 2

使用组合的方式可以很方便的做多线程业务逻辑。

上一篇下一篇

猜你喜欢

热点阅读