c++ 多线程编程-thread--如何启动一个线程

1.线程的分离和汇合

 c++ 11之后提供了线程类的thread。

线程是通过创建thread 对象进行执行。

这个对象表明了要执行的任务,最简单的是执行一个函数。

线程执行后,与原来的线程保持什么关系。

如下代码:

join()接口,要等thread 对象线程执行完毕,才能够执行原线程。

detach()接口,不用等待原来的线程处理结束,就可以执行原线程,thread 对象被分离,单独执行。

#include <iostream>
#include<thread>
#include <unistd.h> 
using namespace std;

void do_something()
{
  cout<<"do_something"<<endl;
}
void do_else_something()
{
  cout<<"do_else_something"<<endl;
}
class callback_task{
 public:
   void operator ()()const{
    cout<<"callback_task"<<endl;
    do_something();
    do_else_something();
   }
};
int main()
{
    callback_task f;
    std::thread my_thread(f);
    my_thread.join();
    std::thread t2([](){
        do_something();
        do_else_something();
    });
    t2.detach();
    std::cout<<"hellow word"<<endl;
    sleep(1);
}

 运行结果:

callback_task
do_something
do_else_something
hellow word
do_something
do_else_somethin

2.如何向thread 函数传递参数

如果需要向新的线程函数传递参数,只需要造thread 构造函数中添加更多的参数就可以。

#include <iostream>
#include<thread>
#include<string>
#include <unistd.h> 
using namespace std;

void call_back(int n,string const &  z)
{
    for(int i=0;i<n;i++)
    {
        cout<<i<<" "<<z<<endl;
    }
}
int main()
{
    string z{"hi"};
   thread mythread(call_back,3,"hello");
   mythread.join();
   sleep(1);
}

运行结果:

0 hello
1 hello
2 hello

 需要注意的是:

线程具备内部储存空间,参数会按照默认的方式,先复制到该处,新创建的执行线程才能进行访问。 即使按引用传递, 新的线程也会复制。

#include <iostream>
#include<stdio.h>
#include<thread>
#include<string>
#include <unistd.h> 
using namespace std;

void call_back(int n,string const &  z)
{
    for(int i=0;i<n;i++)
    {
        cout<<i<<" "<<z<<endl;
        printf("z: %p \n",&z);
    }
}
int main()
{
    string z{"hi"};
   printf("z: %p \n",&z);
   thread mythread(call_back,3,z);
   mythread.join();
   sleep(1);
}

可以看到地质发生了变化

z: 0x7fff48f68b30
0 hi
z: 0x55606ffb0288
1 hi
z: 0x55606ffb0288
2 hi
z: 0x55606ffb0288

按地址传递没有问题,只是将地址传递第副本,毕竟访问的地址指向的值。

#include <iostream>
#include<stdio.h>
#include<thread>
#include<string>
#include <unistd.h> 
using namespace std;

void call_back(int n,string *  z)
{
    for(int i=0;i<n;i++)
    {
        cout<<i<<" "<<*z<<endl;
        printf("z: %p \n",z);
    }
}
int main()
{
    string  z{"hi"};
   printf("z: %p \n",&z);
   thread mythread(call_back,3,&z);
   mythread.join();
   sleep(1);
}

结果:

z: 0x7ffe87fbcad0
0 hi
z: 0x7ffe87fbcad0
1 hi
z: 0x7ffe87fbcad0
2 hi
z: 0x7ffe87fbcad0

如何按引用传递呢:

使用:std::ref()

//如何理解呢,c++11 引入的std::bind() 和thread() 的构造函数类似,以及std::ref()函数。

int main()
{
    string z{"hi"};
   printf("z: %p \n",&z);
   thread mythread(call_back,3,std::ref(z));
   mythread.join();
   sleep(1);
}

z: 0x7ffcb6dccfa0
0 hi
z: 0x7ffcb6dccfa0
1 hi
z: 0x7ffcb6dccfa0
2 hi
z: 0x7ffcb6dccfa0

3. 使用类的成员函数作为线程函数

#include <iostream>
#include<stdio.h>
#include<thread>
#include<string>
#include <unistd.h> 
using namespace std;
class X{
    public:
       void do_something();

};
int main()
{
    X m_x;
    std::thread t(&X::do_something,&m_x);
    t.join();
    sleep(1);
}

 //如何理解这个构造函数:

将m_x的地址传递给thread 的构造函数,因为新的线程会调用:

&m_x->do_something()。

如果有第三个变量,会将值传递给成员函数作为参数。

4 移动与thread 传递的使用

  c++11 加入了移动的概念,将某个对象移动到另一个对象的内部,原来的对象被搬空。

#include <iostream>
#include<stdio.h>
#include<thread>
#include<string>
#include <unistd.h> 
using namespace std;
class X{
    public:
      void do_something();

};
void do_x(unique_ptr<X>);
int main()
{
    X m_x;
    unique_ptr<X> ptr(new X);
    thread my_thread(do_x,std::move(ptr));
    my_thread.join();
}

 智能指针与移动函数:

当调用thread 的构造函数的时候,std::move(ptr),会将ptr归属权转移到新的线程空间,然后再转移给do_x。

线程分离运行,使用detach()。

RAII 封装线程:

class thread_guard
{
private:
   std::thread& t;
public:
   explicit thread_guard(std::thread& t_):t(t_)
   {
   }
   ~thread_guard()
   {
    if(t.joinable())
    {
        t.join();
    }
   }
   thread_guard(thread_guard const &) =delete;
   thread_guard& operator = (thread_guard const &) =delete;
};

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值