本文已参与「新人创作礼」活动,一起开启掘金创作之路。
对于线程来说有一个很大的问题就是对数据的同时访问,这里就简单说一点,比如对数据的同时修改,可能就会导致数据的异常,举个例子,两个人在12306上买同一张座位火车票,可以买到吗,很显然,是买不到,这里面就很显然是做了处理,当然12306肯定不仅仅就是简单的线程互斥的处理,这里只是简单的举个例子。接下来进入正轨
1、线程访问
这里就以两个线程调用同一个函数,打印数据来说明一个问题。首先看现象
std::mutex mtx;
void PrintData(int n, char c)
{
for (int i = 0; i < n; i++) {
cout << c;
}
cout << '\n';
}
int main()
{
std::thread t1(PrintData, 100, '*');
std::thread t2(PrintData, 100, '$');
t1.join();
t2.join();
return 0;
}
可以很明显的看到,打印是杂乱无章的,不过这个也很符合逻辑,线程在自己的函数里面随意打印,但是我们并不期待这样的结果,我们希望能够在谁抢到资源后完成后再由下一个线程继续执行
2、lock_guard 互斥
通过lock_guard互斥上锁的性质来处理这个问题,是不是有点类似Java中的synchronized关键字的效果呢
std::mutex mtx;
void PrintData(int n, char c)
{
std::lock_guard<std::mutex> guad(mtx);
for (int i = 0; i < n; i++) {
cout << c;
}
cout << '\n';
}
int main()
{
std::thread t1(PrintData, 100, '*');
std::thread t2(PrintData, 100, '$');
t1.join();
t2.join();
return 0;
}
3、mtx.lock 和 mtx.unlock
std::mutex mtx;
void PrintData(int n, char c)
{
mtx.lock();
for (int i = 0; i < n; i++) {
cout << c;
}
cout << '\n';
mtx.unlock();
}
int main()
{
std::thread t1(PrintData, 100, '*');
std::thread t2(PrintData, 100, '$');
t1.join();
t2.join();
return 0;
}
可以看到通过mutex的上锁和解锁的方式也可以做到互斥的效果