c++ 11 线程支持库 thread

定义于头文件

线程使得程序能在数个处理器核心同时执行。

std::thread

thread 表示单个执行线程。线程允许多个函数同时执行。

线程在构造关联的线程对象时立即开始执行(等待任何OS调度延迟),从提供给作为构造函数参数的顶层函数开始。顶层函数的返回值将被忽略,而且若它以抛异常终止,则调用 std::terminate 。顶层函数可以通过 std::promise 或通过修改共享变量(可能需要同步,见 std::mutex 与 std::atomic )将其返回值或异常传递给调用方。

std::thread 对象也可能处于不表示任何线程的状态(默认构造、被移动、 detach 或 join 后),并且执行线程可能与任何 thread 对象无关( detach 后)。

没有两个 std::thread 对象会表示同一执行线程; std::thread 不是可复制构造 (CopyConstructible) 或可复制赋值 (CopyAssignable) 的,尽管它可移动构造 (MoveConstructible) 且可移动赋值 (MoveAssignable) 。

构造函数

thread() noexcept;            (1) (C++11 起) 

thread( thread&& other ) noexcept;(2) (C++11 起) 

template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args ); (3) (C++11 起) 

thread(const thread&) = delete;    (4) (C++11 起) 

构造新的 thread 对象。

1) 构造不表示线程的新 thread 对象。

2) 移动构造函数。构造表示曾为 other 所表示的执行线程的 thread 对象。此调用后 other 不再表示执行线程。

3) 构造新的 std::thread 对象并将它与执行线程关联。新的执行线程开始执行

std::invoke(decay_copy(std::forward(f)), 
            decay_copy(std::forward(args))...);

其中 decay_copy 定义为

template 
std::decay_t decay_copy(T&& v) { return std::forward(v); }

除了 decay_copy 的调用在调用方语境求值,故而任何求值和复制/移动参数中抛出的异常被抛到当前线程,而不用开始新线程。

构造函数的调用完成同步于(定义于 std::memory_order )新的执行线程上 f 副本的调用开始。

若 std::decay_t 是与 std::thread 相同的类型,则此构造函数不参与重载决议。

(C++14 起)

4) 复制构造函数被删除; thread 不可复制。没有二个 std::thread 对象可表示同一执行线程。

参数

other - 用以构造此 thread 的另一 thread 对象
f - 执行于新线程的可调用 (Callable)
args... - 传递给新函数的参数

后置条件

1) get_id() 等于 std::thread::id() (即 joinable 为 false )

2) other.get_id() 等于 std::thread::id() 而 get_id() 返回构造开始前 other.get_id() 的值

3) get_id() 不等于 std::thread::id() (即 joinable 为 true )

异常

3) 若不能开始线程则抛出 std::system_error 。异常可能表示错误条件 std::errc::resource_unavailable_try_again 或另一实现限定的错误条件。

注意

到线程函数的参数被移动或按值复制。若需要传递引用参数给线程函数,则必须包装它(例如用 std::ref 或 std::cref )。

忽略来自函数的任何返回值。若函数抛异常,则调用 std::terminate 。为将返回值或异常传递回调用方线程,可使用 std::promise 或 std::async 。

调用示例

#include 
#include 

using namespace std;

void f1(int n)
{
    for (int i = 0; i < 5; ++i)
    {
        std::cout << "Thread 1 executing, threadid: " << std::this_thread::get_id();
        std::cout << ",  n: " << n << std::endl;
        ++n;
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

void f2(int& n)
{
    for (int i = 0; i < 5; ++i)
    {
        std::cout << "Thread 2 executing, threadid: " << std::this_thread::get_id();
        std::cout << ",  n: " << n << std::endl;
        ++n;
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

class foo
{
public:
    void bar()
    {
        for (int i = 0; i < 5; ++i)
        {
            std::cout << "Thread 3 executing, threadid: "
                      << std::this_thread::get_id() << std::endl;
            ++n;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
    int n = 0;
};

class baz
{
public:
    void operator()()
    {
        for (int i = 0; i < 5; ++i)
        {
            std::cout << "Thread 4 executing, threadid: "
                      << std::this_thread::get_id() << std::endl;
            ++n;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
    int n = 0;
};


int main()
{
    int n = 0;
    foo f;
    baz b;

    std::thread t1; // t1 不是线程
//    std::thread t2(f1, n + 1);// 按值传递
    std::thread t3(f2, std::ref(n)); // 按引用传递
    std::thread t4(std::move(t3)); // t4 现在运行 f2() 。 t3 不再是线程
//    std::thread t5(&foo::bar, &f); // t5 在对象 f 上运行 foo::bar()
//    std::thread t6(b); // t6 在对象 b 上运行 baz::operator()

//    t2.join();
    t3.join();
    t4.join();
//    t5.join();
//    t6.join();

    return 0;
}

检查线程是否可合并,即潜在地运行于平行环境中

std::thread::joinable
bool joinable() const noexcept;             (C++11 起) 

检查 thread 对象是否标识活跃的执行线程。具体是返回 true if get_id() != std::thread::id() 。故默认构造的 thread 不可合并。

完成执行代码,但未被合并的线程仍被认为是活跃线程,从而可合并。

参数

(无)

返回值

若 thread 对象标识活跃的执行线程则为 true ,否则为 false

返回线程的 id

std::thread::get_id
std::thread::id get_id() const noexcept;             (C++11 起) 

返回标识与 *this 关联的线程的 std::thread::id 类型值。

参数

(无)

返回值

标识与 *this 关联的线程的 std::thread::id 类型值。若无关联的线程,则返回默认构造的 std::thread::id 。

返回底层实现定义的线程句柄

std::thread::native_handle
native_handle_type native_handle();        (C++11 起) 

返回实现定义的底层线程句柄。

参数

(无)

返回值

表示线程的实现定义句柄类型。

异常

(无)

返回实现支持的并发线程数

std::thread::hardware_concurrency
static unsigned int hardware_concurrency() noexcept;         (C++11 起) 

返回实现所支持的并发线程数。应该只把值当做提示。

参数

(无)

返回值

支持的并发线程数。若值非良定义或不可计算,则返回 ​0​ 。

调用示例

unsigned int n = std::thread::hardware_concurrency();
std::cout << n << " concurrent threads are supported.\n";

等待线程完成其执行

std::thread::join
void join();            (C++11 起) 

阻塞当前线程,直至 *this 所标识的线程完成其执行。

*this 所标识的线程的完成同步于join() 的成功返回。

参数

(无)

返回值

(无)

后置条件

joinable 为 false

异常

若错误发生则为 std::system_error 。

错误条件

  • 若 this->get_id() == std::this_thread::get_id() (检测到死锁)则为 resource_deadlock_would_occur
  • 若线程非法则为 no_such_process
  • 若 joinable 为 false 则为 invalid_argument

容许线程从线程句柄独立开来执行

std::thread::detach
void detach();         (C++11 起) 

从 thread 对象分离执行的线程,允许独立地继续执行。一旦线程退出,则释放所有分配的资源。

调用 detach 后, *this 不再占有任何线程。

参数

(无)

返回值

(无)

后置条件

joinable 为 false

异常

若 joinable() == false 或错误发生时为 std::system_error 。

交换二个 thread 对象

std::thread::swap
void swap( thread& other ) noexcept;         (C++11 起) 

互换二个 thread 对象的底层句柄。

参数

other - 要与之交换的 thread

返回值

(无)

你可能感兴趣的:(#,线程支持库,c++,多线程)