前言
一次,我封装了一个互斥锁,然后,打算写个程序测试一下。于是写了大概如下代码:
#include <memory> #include <stdio.h> #include <future> #include <chrono> #include <semaphore.h> #include <exception> class Mutex { public: Mutex() { if (sem_init(&sem_, 0, 0) != 0) throw std::logic_error("sem_init"); } ~Mutex() { sem_destroy(&sem_); } void lock() { if (sem_post(&sem_) != 0) throw std::logic_error("sem_post"); } void unlock() { if (sem_wait(&sem_) != 0) throw std::logic_error("sem_post"); } private: Mutex(const Mutex&) = delete; Mutex(const Mutex&&) = delete; Mutex& operator=(const Mutex&) = delete; Mutex& operator=(const Mutex&&) = delete; sem_t sem_; }; int main() { Mutex mtx; std::async([&mtx] { mtx.unlock(); }); std::async([&mtx] { mtx.lock(); }); }
乍一看,应该没啥问题,可是,为啥卡死了,难道死锁了?
解决过程
把 async 换成 thread,可以正常运行。问题来了,async,这个被推荐使用的函数,它咋了
后来,我看到了这段话
若从 std::async 获得的 std::future 未被移动或绑定到引用,则在完整表达式结尾, std::future 的析构函数将阻塞直至异步计算完成,实质上令如下代码同步:
std::async(std::launch::async, []{ f(); }); // 临时量的析构函数等待 f()
std::async(std::launch::async, []{ g(); }); // f() 完成前不开始
对应上面的代码,也就是说,加锁那块会等待解锁的完成,才能继续执行下去,这就形成了死锁,如果改成这样就没问题了:
auto a = std::async([&mtx] { mtx.unlock(); }); std::async([&mtx] { mtx.lock(); });
结论
以调用 std::async 的方式获得的 std::future 的析构函数会阻塞程序的执行
同理的代码为:
void func() { auto a = std::async([]{ std::this_thread::sleep_for(std::chrono::seconds(1)); }); } int main() { func(); puts("hello"); return 0; }
来源:https://www.cnblogs.com/zuofaqi/p/12380792.html