从C++11开始,标准库就开始有了并发支持库,其中就包括mutex 互斥量的支持。
mutex提供用于保护共享数据免受从多个线程同时访问的功能。下面是一个简单的例子:
#include
#include
#include
using namespace std;
mutex smutex;
long sumval = 0;
void threadsum()
{
for (long i=0;i<100000;i++)
{
smutex.lock();
sumval++;
smutex.unlock();
}
}
int main()
{
for (int i=0;i<10;i++)
{
thread(threadsum).detach();
}
this_thread::sleep_for(1000ms);
std::cout << "Sum Value:" << sumval << std::endl;
} 如果没有互斥量smutex的支持,Sum Value的结果是不固定的:
Sum Value:347214mutex的用法也比较简单:
smutex.lock(); //锁定互斥量,如果已被锁定,则无限等待
//xxx 锁定区域内的代码,多线程安全
smutex.unlock(); //解除锁定为了避免无限等待问题,还提供try_lock指令,如果可以锁定,则返回true,否则 false
还是刚才的例子:
void threadsum()
{
for (long i=0;i<100000;i++)
{
for (;;)
{
if (smutex.try_lock())
{
sumval++;
smutex.unlock();
break;
}
else
{
std::cout << "try_lock NG retry!
";
}
}
}
}但是还是不太灵活,所以C++11有提供了timed_mutex类,这样就可以提供有超时特性的 mutex。相对于mutex,增加了两个成员函数 try_lock_for以及try_lock_until。
t_mutex.try_lock_for(100ms); //尝试在100ms内锁定互斥量,如果成功返回true
auto now=std::chrono::steady_clock::now();
t_mutex.try_lock_until(now + 100ms); //尝试在now时间的基础上叠加100ms内锁定互斥量,如果成功返回true另外的,由于互斥的特性,在已经锁定互斥量的基础上,再次尝试锁定,会死锁或者异常。在某些特殊的情况不利于代码快速编写。
所以C++11还提供了递归锁——recursive_mutex以及recursive_timed_mutex。
对于如下代码,采用常规mutex会异常,换成递归锁正常执行,方便很多递归函数的互斥。
std::mutex addMutex;
//std::recursive_mutex addMutex;
void addfun(int &nowt)
{
addMutex.lock();
if(nowt>=0)
{
nowt--;
std::cout << "nowt--
";
addfun(nowt);
}
addMutex.unlock();
}很多时候互斥只需求锁定修改权限,而读取权限不单独锁定,即读写锁,C++提供了以下类:
class RWMutex {
public:
RWMutex() = default;
// 能同时读计数器的值。
void read(unsigned int &res)
{
mutex_.lock_shared();
std::cout << "Enter Read
";
res= value_;
//this_thread::sleep_for(1000ms);
mutex_.unlock_shared();
}
// 只有一个能写
void write() {
mutex_.lock();
std::cout << "Enter Write
";
value_++;
this_thread::sleep_for(1000ms);
mutex_.unlock();
}
private:
std::shared_mutex mutex_;
unsigned int value_ = 0;
};
int main() {
RWMutex mutextest;
auto testthread = [&]() {
for (int i = 0; i < 3; i++) {
//mutextest.write();
unsigned int res;
mutextest.read(res);
std::cout << "threadid:"<threadlist;
for (int i=0;i<10;i++)
{
threadlist.emplace_back(std::thread(testthread));
}
for (int i = 0; i < 10; i++)
{
threadlist[i].join();
}
} 如上例展示,增加了lock_shared、unlock_shared、try_lock_shared以及
try_lock_shared_for、try_lock_shared_until等系列成员函数。
The End~
| 留言与评论(共有 0 条评论) “” |