C++11特性学习

1.std::thread

thread& operator=( thread&& other ) noexcept

thread对象创建就不讲了,但是给已经创建的thread对象赋值需要注意:

1)如果左值是运行中进程(可joinable()==true),则在进行move 赋值时会调用terminate接收进程并抛异常。
2)如果左值运行的进程以及detach了,则不会call terminate;
3)如果左值是空thread 对象,则直接move赋值。

2. 互斥变量

std::mutex,最基本的 Mutex 类。
std::recursive_mutex,递归 Mutex 类。
std::timed_mutex,定时 Mutex 类。
std::recursive_timed_mutex,定时递归 Mutex 类

std::mutex 既不可复制亦不可移动。mutex 提供排他性非递归所有权语义:
                   bool try_lock();尝试锁定互斥。立即返回。成功获得锁时返回 true ,否则返回 false

std::recursive_mutex,递归 Mutex 类。排他性递归所有权语义.在同一个线程内对各个函数上锁解锁分而治之。
从它成功调用 lock 或 try_lock 开始的时期里占有 recursive_mutex 。此时期间,线程可以进行对 lock 或 try_lock 的附加调用。所有权的时期在线程调用 unlock 匹配次数时结束。

线程占有 recursive_mutex 时,若其他所有线程试图要求 recursive_mutex 的所有权,则它们将阻塞(对于调用 lock )或收到 false 返回值(对于调用 try_lock )。
可锁定 recursive_mutex 次数的最大值是未指定的,但抵达该数后,对 lock 的调用将抛出 std::system_error 而对 try_lock 的调用将返回 false 。


std::timed_mutex 类是能用于保护数据免受多个线程同时访问的同步原语。timed_mutex 提供排他性非递归所有权语义。
try_lock_for 函数在 “一段时间范围之内” 线程如果没有获得锁则被阻塞住,直到在此期间内其他线程释放了锁,则该线程可以获得对互斥量的锁返回,或在指定时间内还是没有获得锁, 超时返回 false。


  using Ms = std::chrono::milliseconds;
  std::this_thread::sleep_for(Ms(100)); //mtx.try_lock_for(std::chrono::milliseconds(200))

try_lock_until 函数则接受 “一个时间点” 作为参数,在指定时间点未到来之前线程如果没有获得锁则被阻塞住,如果在此期间其他线程释放了锁,则该线程可以获得对互斥量的锁返回,如果到达指定时间点没有获得锁,则返回 false。


    auto now=std::chrono::steady_clock::now();
    test_mutex.try_lock_until(now + std::chrono::seconds(10));

3. 互斥封装器

std::lock_guard,与 Mutex RAII 相关,方便线程对互斥量上锁。不可移动不可复制。
————互斥封装器,创建后在作用域块期间占有互斥, 离开创建lock_guard 对象的作用域时自动销毁。

std::unique_lock 方便线程对互斥量上锁,但提供了更好的上锁和解锁控制。可移动不可复制。
通用互斥包装器,允许延迟锁定、锁定的有时限尝试、递归锁定、所有权转移和与条件变量一同使用。
若 Mutex 满足可锁 (Lockable) 要求,则 unique_lock 亦满足可锁 (Lockable) 要求(例如:能用于 std::lock ) ;
若 Mutex 满足定时可锁 (TimedLockable) 要求,则 unique_lock 亦满足定时可锁 (TimedLockable) 要求。
std::unique_lock重载了lock和unlock方法,它可以作为std::lock的参数;而std::lock_guard不行。
std::unique_lock的实例不依赖于std::mutex等锁,所以在初始化的时候,他有空构造函数的,
这就导致了std::unique_lock的锁有两种状态,即内部有无锁,这个可以通过bool std::unique_lock.owns_lock()来检测;
explicit operator bool() const noexcept; (C++11 起) 检查 *this 是否占有互斥。等效地调用 owns_lock() 

release  将关联互斥解关联,而不解锁它。返回之前关联的互斥,如果关联互斥为空则返回nullptr 
_Mutex *release()_ noexcept

    //disconnect
    _Mutex * _Res = _Pmtx;
    _Pmtx = nullptr;
    _Owns = false
    return (_Res);
}

包装器对象在operator= 赋值时,如果已经lock关联互斥,则会先解锁,再替换unique_lock对象。

1) explicit unique_lock( mutex_type& m );默认构造是通过调用 m.lock() 锁定关联互斥。

2)构造使用try_to_lock_t 尝试锁定关联互斥而不阻塞 (作用是告诉构造函数,请尝试获取锁的所有权;)
3)std::defer_lock,作用是告诉构造函数,不锁定关联互斥,将会在后续的执行中进行获取。
这里的一个应用是用std::lock给std::unique_lock上锁


      std::unique_lock lk_b(m_b, std::defer_lock);
      std::unique_lock lk_c(m_c, std::defer_lock);
      std::lock(lk_b, lk_c);


4)adopt_lock_t 调用方线程已拥有互斥的所有权(告诉构造函数,在构造之前,该锁的所有权就已经被获取,请不要尝试获取)


    std::lock(from.m, to.m);
    // 保证二个已锁定互斥在作用域结尾解锁
    std::lock_guard lock1(from.m, std::adopt_lock);
    std::lock_guard lock2(to.m, std::adopt_lock);


4. promise - future 结构


std::promise 不可复制,可move。


void print_int(std::future& fut) {
    printf("==\n");fflush(stdout);
    int x = fut.get(); // 阻塞等待,获取共享状态的值.
    std::cout << "value: " << x << '\n'; // 打印 value: 10.
}
//promise 是 promise-future 交流通道的“推”端
int main(){
    std::promise prom; // 生成一个 std::promise 对象.
    std::future fut = prom.get_future(); // 和 future 关联.
    std::thread t(print_int, std::ref(fut)); // 将 future 交给另外一个线程t.
    sleep(3);
    prom.set_value(10); // 设置共享状态的值, 此处和线程t保持同步. 存储值于共享状态的操作与等待函数fut.get()同步
    t.join();
    
    return 0;
}

std::future accumulate_future = accumulate_promise.get_future();
//accumulate_future.wait();  // 等待结果
//get 方法等待直至 future 拥有合法结果并(依赖于使用哪个模板)获取它。它等效地调用 wait() 等待结果。

printf("do wait\n");fflush(stdout);
std::cout << "result=" << accumulate_future.get() << '\n';fflush(stdout);
printf("do wait over\n");fflush(stdout);


std::call_once,如果多个线程需要同时调用某个函数,call_once 可以保证多个线程对该函数只调用一次。

你可能感兴趣的:(C++,c++,学习,开发语言)