线程的创建

线程管理


启动线程

线程在thread对象创建时开始启动,传递给线程的函数运行结束时,线程也结束。

//线程thread构造函数:
template<class _Fn,class... _Args>
explicit thread(_Fn&& _Fx, _Args&&... _Ax)
{   // construct with _Fx(_Ax...)   
    _Launch(
    &_Thr,
    _STD bind(_Decay_copy(_STD forward<_Fn>(_Fx)),
    _Decay_copy(_STD forward<_Args>(_Ax))...)
    );
}
thread(thread&& _Other) _NOEXCEPT
        : _Thr(_Other._Thr)
        {   // move from _Other
        _Thr_set_null(_Other._Thr);
        }

    thread& operator=(thread&& _Other) _NOEXCEPT
        {   // move from _Other
        return (_Move_thread(_Other));
        }

在启动了线程之后,需要使用join()和detach()来确定主线程要等待线程结束还是让其自主运行到结束。detach()相当于让线程在后台运行
如果不等待线程结束,则要保证线程结束之前,可访问数据的有效性!要解决这种情况,可以将数据复制到线程中。
一个线程只能使用一次join(),一旦使用过join(),thread对象就不能再次加入了。

向线程函数传递参数

void foo(int i, const string& s);
thread t(f00,3,"hello");

此时,代码创建了一个调用foo(3,”hello”)的线程。
当指向动态变量的指针作为参数传递给线程

转移线程的所有权

因为thread的构造函数中使用了右值引用&&,所以可以接收一个右值参数。使用std::move()可以强制把左值转换成右值,因此可以理解为转移线程的所有权,有点类似于剪切-粘贴的操作。
实质上是把新的对象绑定原线程的内存块,然后使原对象的绑定失效。

void fun();
thread t(fun);
thread t1 = std::move(t);

对于如上代码,首先创建线程t,然后使用std::move()函数将t所拥有的线程转移给t1,转移之后该线程所有的资源都转移给t1,t与该线程没有任何关联。

因为thread支持移动,当一个函数返回一个thread对象时,该对象就是一个右值,因此新创建的线程对象可以利用该右值进行初始化。

std::thread f(){
    void func();
    return std::thread(func);
}
std::thread t = f();

甚至可以把线程传入类进行操作

class myThread{
public:
    myThread(thread t_):t(move(t_)){}
}

你可能感兴趣的:(C++)