一、C++11中提供了std::mutex互斥量,共包含四种类型:
std::mutex:最基本的mutex类。
二、C++11提供了两种管理锁的类
std::lock_guard:与mutex RAII相关,方便线程对互斥量上锁
std::unique_lock: 与mutex RAII相关,方便线程对互斥量上锁,相比std::lock_guard提供了更好的上锁和解锁控制
三、互斥锁 lock()
介绍上锁不上锁情况!
例子:100个人分别购买100000张票,多线程
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex
volatile int counter(0); // non-atomic counter
std::mutex mtx; // locks access to counter
void attempt_10k_increases() {
for (int i=0; i<100000; ++i)
{
// mtx.lock(); //分别试试 如果不加锁 与加锁区别
++counter;//counter++ 不是 原子操作
// mtx.unlock();
}
}
int main (int argc, const char* argv[]) {
std::thread threads[100];//100个人分别购买100000张票
for (int i=0; i<100; ++i)
threads[i] = std::thread(attempt_10k_increases);
for (auto& th : threads) th.join();// 令线程加入等待.调用该函数会阻塞当前线程。阻塞调用者(caller)所在的线程直至被join的std::thread对象标识的线程执行结束。
std::cout << counter << " successful increases of the counter.\n";
return 0;
}
五、解析:
1、100个人分别购买100000张票,多线程,100个人合作购买会产生预想不一样的结果!!会修改counter!!;如果加上锁,此时写counter会阻挡其他进程访问counter(注意:要解锁,否则会死锁)
2、原子操作就是: 不可中断的一个或者一系列操作, 也就是不会被线程调度机制打断的操作, 运行期间不会有任何的上下文切换(context switch)
3、为什么关注原子操作?
3.1. 如果确定某个操作是原子的, 就不用为了去保护这个操作而加上会耗费昂贵性能开销的锁. - (巧妙的利用原子操作和实现无锁编程)
3.2. 借助原子操作可以实现互斥锁(mutex). (linux中的mutex_lock_t)
3.3. 借助互斥锁, 可以实现让更多的操作变成原子操作.
4、结果:
上锁:10000000 successful increases of the counter.
不上锁:(报错)5825663 successful increases of the counter.