读书笔记《C++并发编程实战》(3) - 线程间数据共享
竞争条件: 进程中各个线程可共享数据,既是优点也是缺点,而导致不同线程操作数据出现异常的情况时,竞争条件是其中之一。 避免竞争条件: 一:采用保护机制,封装正在修改的或访问的数据结构,确保其他线程在共享数据被修改前或修改后才可见可访问。 二:修改数据结构设计、或者使用不变量,如无锁编程(无锁数据结构等)。 互斥体保护: 互斥体作为同步原语,可确保一个线程获取共享数据时锁定资源,并处理资源后解锁,其他线程才可见可访问该资源。 不过需要精心处理互斥体,确保不会出现死锁、保护过多、过少的数据。 std::mutex封装了基本的锁操作,此外使用std::lock_guard类模板实现互斥体的RAII惯用法,以避免显式调用lock/unlock等接口。 另外互斥体一般与受保护的共享数据放在一起,如同一个类中,且需要精心设计避免受保护的数据外泄(如:抛出地址或引用或者传入 了其他可访问受保护的共享数据的外部函数等)。线程已持有std::mutex锁时,若该线程再次获取该锁将出现异常,此时应使用 递归锁std::recursive_mutex。 死锁: 一般在两个或者多个线程拥有对方的锁资源时却相互等待另一方释放所拥有的锁资源。进而产生死锁。这个情况常出现在需要锁定两个 或者更多互斥体或其他原语时以执行操作时最常出现的情形。其他的情形也包括等待相互的另一方线程退出或者其他资源或同步需求时。