导言:随着计算机硬件条件的提升,软件的设计与开发更多的看重其执行速度,而采用多线程并发的执行一些操作对提升效率至关重要。
C++11的出现,给了用户很大的方便,摒弃了原有的windows线程设计函数,而采用了std::thread来设计线程函数,只要包含头文件<thread.h>就行。
1.1 创建线程
std::thread t(func); //func-线程函数名, t-线程名,将线程函数放到线程t中执行。
t.join();//线程执行开始
注意:线程的开始执行方法又两种,join(),或者detach().
join()方法: join()函数将阻塞线程直到线程函数结束
detach()方法: detach()函数将线程和线程对象分离,分离后无法再和线程函数联系,可通过回调返回其执行结果。
1.2 创建线程+lamada表达式
1.2.1 lamada的格式:[ 捕获值方式](形参){函数体}
捕获值方式有以下几种:
[ &]:引用捕获,直接引用线程外部函数的值,缺点是:在并发执行过程中,很可能线程所在的类已经析构,而线程函数还在执行,这样将导致线程函数引用的值不存在,而导致崩溃。
[ =]:拷贝方式捕获,拷贝一份外部函数中的变量值,跟随线程函数执行,这种方式较为稳妥
[ bar]:拷贝外部变量bar的副本供线程函数使用
[ this]:捕获当前类中的this指针,让lamada表达式拥有和当前类成员函数同样的访问权限。即:使用
当前类的成员函数和成员变量。
1.2.2 互斥量
在线程的运行过程中,多个线程竞争同一资源的情况下,需要用到互斥锁来防止资源被破坏
std::mutex m_lock;
例如
void func()
{
m_lock.lock();//加锁
funcrate();
m_lock.lock();//解锁
}
还有一个lock_gurd,不需要进行加锁和解锁的频繁操作
void func()
{
std::lock_guard<std::mutex> locker(m_lock);//加锁,自动解锁
funcrate();
}
递归互斥量:避免一个线程多次获取互斥量时死锁
例如:std::recursive_mutex m_mutex;
1.2.3 条件变量(另一种线程同步的方法,它将阻塞一个或多个线程直到收到另外一个线程)
condition_variable, 配合std::unique_lock<std::mutex> 进行wait操作
condition_variable_any, 可配合任意带有lock、unlock语义的mutex 搭配使用,使用灵活
1.4 lamada+std::thread一起使用
void Func(const std::wstring& file,IAddFileCallback* pCallback)
{
int nNum=10;
std::thread t([=]()
{
shortfunc( file);
nNum++;
if (pCallback)
{
wstring strLocalCachePath = L"";
if (bResult)
strLocalCachePath = m_strLoacalParentPath + strRelativePath;
pCallback->OnFileCallback(strRelativePath, strLocalCachePath, bResult);
}
}
)
t.detach();
}
std::ref(num);//直接拷贝对象,不需要引用
1.5 线程异步获取返回值
可以使用是std::future来获取线程返回值
reterance:https://www.cnblogs.com/haippy/p/3280643.html
例如:
bool do_check_prime(int x) // 为了体现效果, 该函数故意没有优化. { for (int i = 2; i < x; ++i) if (x % i == 0) return false; return true; }
int mian()
{
std::future < bool > fut = std::async(do_check_prime, 194232491); std::cout << "Checking...\n"; fut.wait();//等待。。。 std::cout << "\n194232491 "; if (fut.get()) // guaranteed to be ready (and not block) after wait returns std::cout << "is prime.\n"; else std::cout << "is not prime.\n"; return 0; }