锁主要在两个以上的线程中使用,当多个线程访问共享资源时,我们需要使用锁,开保证共享资源的唯一性。
当两个线程访问不带锁的共享资源时,如下代码
#include<array>
#include<thread>
#include<iostream>
using namespace std;
void inc(int& res)
{
for (int i = 0; i < 1000000; i++)
res++;
}
int main1()
{
int counter = 0;
thread th1(inc,ref(counter));
thread th2(inc, ref(counter));
th1.join();
th2.join();
cout << "counter =" << counter << "\n";
return 0;
}
得到结果
显然结果是不正确的。
这时我们需要加锁来限制
#include<array>
#include<thread>
#include<iostream>
#include<mutex>
using namespace std;
class Counter {
public:
void inc()
{
counter_mutex.lock();
m_count++;
counter_mutex.unlock();
}
int getCounter() //如果在多线程调用也需要加锁 这里没在多线程调用也加了锁
{
int temp;
counter_mutex.lock();
temp = m_count;
counter_mutex.unlock();
return temp;
}
private:
mutex counter_mutex;
int m_count = 0;
};
int main2()
{
Counter counter;
auto increase = [](Counter& counter)
{
for (int i = 0; i < 1000000; i++)
counter.inc();
};
thread th1(increase, ref(counter));
thread th2(increase,ref(counter));
th1.join();
th2.join();
cout << "counter=" << counter.getCounter()<<"\n";
return 0;
}
由于上述加锁,代码的健壮性不是很好,如果遇到异常抛出情况,可能存在互斥量未释放问题。所以进一步改进
如下代码
#include<array>
#include<thread>
#include<iostream>
#include<mutex>
using namespace std;
class Counter {
public:
void inc()
{
lock_guard<mutex> lock(counter_mutex);
m_count++;
}
int getCounter()
{
int temp;
lock_guard<mutex> lock(counter_mutex);
temp = m_count;
return temp;
}
private:
mutex counter_mutex;
int m_count = 0;
};
int main2()
{
Counter counter;
auto increase = [](Counter& counter)
{
for (int i = 0; i < 1000000; i++)
counter.inc();
};
thread th1(increase, ref(counter));
thread th2(increase,ref(counter));
th1.join();
th2.join();
cout << "counter=" << counter.getCounter()<<"\n";
return 0;
}
这样只要不在作用域范围内,锁就会释放,可以避免上述问题。
unique_lock更加灵活,可以创建后不锁定,在使用过程中进行锁定。
#include<array>
#include<thread>
#include<iostream>
#include<mutex>
using namespace std;
class Counter
{
public:
void increase(int n)
{
unique_lock<mutex>lock(counter_mutex,defer_lock);//延迟获取锁
while (n--)
{
lock.lock();
m_count++;
lock.unlock();
}
}
int getCount()
{
unique_lock<mutex> lock(counter_mutex);
return m_count;
}
private:
mutex counter_mutex;
int m_count = 0;
};
void main3()
{
Counter counter;
auto increase = [](Counter& counter) {
counter.increase(1000000);
};
thread th1(increase, ref(counter));
thread th2(increase, ref(counter));
th1.join();
th2.join();
cout << "counter=" << counter.getCount() << "\n";
}
还有一种计时锁,设定在多少时间内进行锁定
#include<array>
#include<thread>
#include<iostream>
#include<mutex>
using namespace std;
//time_mutex
using namespace std::chrono_literals;
class TryDemo
{
public:
void print()
{
for (int i =0; i < 10; i++)
{
unique_lock<timed_mutex>lock(m_mutex,defer_lock);
if (lock.try_lock_for(100ms))//100ms是否获得该锁
{
{
lock_guard<mutex> guard(count_mutex);
cout << "[" << this_thread::get_id << "]" << "成功;\n";
}
this_thread::sleep_for(100ms);
}
else
{
lock_guard<mutex> lock_guard(count_mutex);
cout << "[" << this_thread::get_id() << "]" << "失败;\n";
this_thread::sleep_for(100ms);
}
}
}
private:
timed_mutex m_mutex;
mutex count_mutex;
int m_count = 0;
};
void main5()
{
TryDemo demo;
auto print = [](TryDemo& demo)
{
demo.print();
};
thread th1(print,ref(demo));
thread th2(print, ref(demo));
th1.join();
th2.join();
}