C++ 线程互斥
竞态条件:多线程执行结果应该是一致的,不应该因CPU 对线程的调用顺序不一样,而导致结果不一样,这也是多线程对全局量的共享,导致数据不一致,因此要保证线程的安全
例子如下:
#include<iostream> #include<stdlib.h> #include<string.h> #include<string> #include<unistd.h> #include<list> #include<thread> using namespace std; int count = 100; // 模拟卖票的线程函数 void SellTicket(int i) { while(count>0) { cout<<"窗口"<<i<<"卖出第"<<count<<"张票"<<endl; count--; std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } } int main() { list<std::thread> tlist; for(int i = 0 ;i < 3; i++) { tlist.push_back(std::thread(SellTicket,i)); } for(std::thread &t : tlist) { t.join(); } cout<<"所有窗口完成卖票"<<endl; return 0; }
当把数据从内存读到寄存器中,通过运算单元计算完,并没有写回内存,这个线程被挂起,那么就会导致内存中的数据没有被修改,因此需要使用互斥锁。
#include<iostream> #include<stdlib.h> #include<string.h> #include<string> #include<unistd.h> #include<list> #include<thread> #include<mutex> using namespace std; int count = 100; std::mutex mtu; // 模拟卖票的线程函数 void SellTicket(int i) { while(count>0) { mtu.lock(); // 这里还是存在问题,当count 为1 的时候,此时有两个线程都进来,但是一个线程没有真正的进行count-- , 那么另一个线程阻塞在lock() ,当 // 第一个线程释放锁之后,那么第二个线程还是会进行count-- ,不正确。 // 因此需要锁加双层判断 if(count >0 ) { cout<<"第"<<i<<"窗口:"<<count<<endl; count--; } mtu.unlock(); std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } int main() { list<std::thread> tlist; for(int i = 0 ;i < 3; i++) { tlist.push_back(std::thread(SellTicket,i)); } for(std::thread &t : tlist) { t.join(); } cout<<"所有窗口完成卖票"<<endl; return 0; }
这里就使用了 std::mutex
这里有点像智能指针一样管理互斥锁 lock_guard (是个类 接收一个互斥锁) // 类似于智能指针的scoped_ptr
例如 :std::mutex mut;
lock_guard<std::mutex> lock(mut); // 保证unlock() 一定被调用到,不会造成死锁
当出作用域就析构,也就是释放锁
unique_lock 允许右值引用的拷贝构造和赋值
unique_lock<std::mutex> _lock(mut):
_lock.lock();
_lock.unlock();