首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么` `std::lock`不使用全局排序锁定互斥锁?

std::lock是C++标准库中的一个函数,用于同时锁定多个互斥锁,以避免死锁和提高并发性能。它的设计目的是为了解决多个互斥锁的死锁问题。

在实现上,std::lock函数使用了一种叫做"锁的层级化"的技术,而不是全局排序锁定互斥锁。全局排序锁定互斥锁是一种简单的方法,它要求所有线程按照某种全局顺序来获取互斥锁,以避免死锁。然而,这种方法存在一些问题。

首先,全局排序锁定互斥锁会引入额外的开销。因为所有线程都必须按照全局顺序来获取互斥锁,这就需要维护一个全局的锁定顺序,而且每次获取互斥锁都需要检查这个顺序。这会增加锁的竞争和系统开销。

其次,全局排序锁定互斥锁会限制并发性能。因为所有线程都必须按照全局顺序来获取互斥锁,这就导致了所有线程之间的串行化。如果一个线程在获取互斥锁时被阻塞,那么其他线程也必须等待,即使它们之间没有竞争关系。这会降低系统的并发性能。

相比之下,std::lock函数使用了一种更高效的层级化锁定策略。它会根据互斥锁的地址来确定锁的层级关系,并按照层级顺序来获取互斥锁。这样可以避免全局排序锁定互斥锁的开销和并发性能问题。

总结起来,std::lock不使用全局排序锁定互斥锁的原因是为了避免额外的开销和限制并发性能。它采用了一种更高效的层级化锁定策略,以解决多个互斥锁的死锁问题。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

来聊聊C++中头疼的线程、并发

其中std::mutex表示普通互斥,可以与std::unique_lock配合使用,把std::mutex放到unique_lock中时,mutex会自动上锁,unique_lock析构时,同时把mutex...常用的成员函数有: 构造函数:std::mutex不支持copy和move操作,最初的mutex对象处于unlocked状态。 lock函数:互斥锁定。...std::try_to_lock 表示我们会尝试用mutex的lock锁定这个mutex,如果没有锁定成功,就立即返回,并不会阻塞在哪里。...unlock() try_lock() 尝试给互斥量加锁,阻塞。...当多个线程访问同一共享资源时,不但需要用互斥实现独享访问以避免并发错误(竞争危害),在获得互斥进入临界区后还需要检验特定条件是否成立: 若不满足该条件,拥有互斥的线程应该释放该互斥使用unique_lock

4.7K41

线程同步与互斥

编程 不是什么时候都要靠上锁的。从根源出发,我们为什么需要上锁?因为线程在使用资源的过程中可能会出现冲突,对于这种会出现冲突的资源,还是锁住轮着用比较好。...3️⃣重试代价:如果重试代价大,建议采用悲观。悲观依赖数据库,效率低。更新失败的概率比较低。 自旋 互斥:阻塞等待,wait() 自旋:等两下就去问一声:好了?我很急啊!好了?...unique_lock是一个通用的互斥锁定包装器,它允许延迟锁定,限时深度锁定,递归锁定锁定所有权的转移以及与条件变量一起使用。...特点如下: 创建时可以锁定(通过指定第二个参数为std::defer_lock),而在需要时再锁定 可以随时加锁解锁 作用域规则同 lock_grard,析构时自动释放 不可复制,可移动 条件变量需要该类型的作为参数...但是互斥一个明显的缺点是它只有两种状态:锁定和非锁定

79510

C++ std::unique_lock 用法

你可以在构造函数中传入一个互斥std::mutex 或其它互斥类型)来创建 std::unique_lock 对象,并且会在构造时获取互斥的所有权。...3.延迟加锁与手动加解锁 std::unique_lock 还支持在初始化时立即加锁,而是在需要时延迟加锁。...: lock.lock(); // 手动加锁 // 临界区代码 lock.unlock(); // 手动解锁 你可以使用 lock() 手动加锁,然后在互斥保护的临界区内执行代码,最后使用 unlock...请注意,返回前调用 lck.lock() 加锁可能会再次阻塞线程。 为什么条件变量需要互斥的配合呢? 因为 condition 和等待队列都是多线程的共享资源,当访问这些共享资源时需要互斥访问。...在多数情况下,推荐使用 std::unique_lock 而不是直接操作互斥,因为它能够自动管理的生命周期,减少了出错的机会。

95320

线程同步-The Boost C++ Libraries

这将导致线程等待,直到拥有互斥的线程完成处理并释放其对该互斥的所有权为止。 示例44.7使用类型为boost::mutex的全局互斥,称为互斥。...两种变体仍然在循环中向标准输出流写入五个数字,但是现在它们使用类boost::unique_lock锁定互斥体。...thread1()将变量互斥传递给boost::unique_lock的构造函数,这使boost::unique_lock尝试锁定互斥。...这使得boost::unique_lock的构造函数不调用互斥锁上的lock(),而是调用try_lock()。因此,构造函数仅尝试锁定互斥。如果互斥由另一个线程拥有,则尝试失败。...owns_lock()可让您检测boost::unique_lock是否能够锁定互斥。如果owns_lock()返回true,thread2()可以立即访问std::cout。

80010

并发编程(从C++11到C++17)

所以这些类都提供了下面三个方法,并且它们的功能是一样的: 方法 说明 lock 锁定互斥体,如果不可用,则阻塞 try_lock 尝试锁定互斥体,如果不可用,直接返回 unlock 解锁互斥体 这三个方法提供了基础的锁定和解除锁定的功能...,获得互斥的所有权 try_to_lock C++11 类型为try_to_lock_t,尝试获得互斥的所有权而阻塞 adopt_lock C++11 类型为adopt_lock_t,假设调用方已拥有互斥的所有权...<< '\n'; } 这段代码中: 1.全局互斥体g_i_mutex用来保护全局变量g_i2.这是一个设计为可以被多线程环境使用的方法。...因此需要通过互斥体来进行保护。这里没有调用lock方法,而是直接使用lock_guard来锁定互斥体。...3.在方法结束的时候,局部变量std::lock_guard lock会被销毁,它对互斥体的锁定也就解除了。4.在多个线程中使用这个方法。

573130

C++17中的shared_mutex与C++14的shared_timed_mutex

独占性 --- 仅一个线程能占有互斥。其对应的就是写的访问权限。 若一个线程已获取独占性(通过 lock、try_lock),则无其他线程能获取该(包括共享的)。...仅当任何线程均未获取独占性时,共享能被多个线程获取(通过 lock_shared、 try_lock_shared)。在一个线程内,同一时刻只能获取一个(共享或独占性)。...shared_mutex提供了排他性锁定方法有: 函数 功能描述 备注 lock 锁定互斥,若互斥不可用则阻塞 公有成员函数 try_lock 尝试锁定互斥,若互斥不可用则返回 公有成员函数 unlock...解锁互斥 公有成员函数 注:通常直接调用 lock() 和unlock(),而是用 std::unique_lockstd::lock_guard管理排他性锁定。...解锁互斥 公有成员函数 注:通常直接调用 lock() 和unlock(),而是用 std::unique_lockstd::lock_guard管理排他性锁定

64920

多线程

,在不同线程访问同一个资源的时候,会发生不一致的情况,为了数据的同步,必须使用 的种类 按照的种类分类,可以分为以下几种 互斥 自旋 条件变量 1....对于互斥锁在C++标准库里有的: std::mutex,可以阻塞式等lock())也可以非阻塞式上锁(try_lock()),lock可以同时锁定几个互斥量,try_lock如果锁定失败会直接返回...,递归互斥,在互斥的基础上允许持有的线程多次通过lock()或者try_lock()获取,而std::mutex的拥有者不能继续请求上锁 std::recursive_timed_mutex...,递归互斥加时版 std::shared_mutex,共享互斥,允许多个线程共享(lock_shared()系列),但只有一个线程能够持有互斥(lock()系列),也就是一般所说的读写...(提前)解锁 std::shared_lock,配合共享使用管理器 再深入了解读写 在c++里实现读写 #include //std::unique_lock #

58520

硬核!C++并发编程(C++11到C++17)

一旦某个线程获取了互斥,任何其他线程都无法再获取互斥和共享;但是如果有某个线程获取到了共享,其他线程无法再获取到互斥,但是还有获取到共享。这里互斥使用和其他的互斥体接口和功能一样。...通用锁定算法 主要API 要避免死锁,需要仔细的思考和设计业务逻辑。 有一个比较简单的原则可以避免死锁,即:对所有的进行排序,每次一定要按照顺序来获取,不允许乱序。...<< '\n'; } 这段代码中: 全局互斥体g_i_mutex用来保护全局变量g_i 这是一个设计为可以被多线程环境使用的方法。...因此需要通过互斥体来进行保护。这里没有调用lock方法,而是直接使用lock_guard来锁定互斥体。...在方法结束的时候,局部变量std::lock_guard lock会被销毁,它对互斥体的锁定也就解除了。 在多个线程中使用这个方法。

1.2K40

46.python GIL互斥Lock的区别

一.python线程互斥Lock python中,当有多个线程threading同时执行时,对同一个全局变量或者同一个文件操作时,如果没有设置互斥,容易造成数据混乱,比如下面这两个案例: 1.案例一...注意:互斥一旦锁定之后要记得解锁,否则资源会一直处于锁定状态,容易造成死锁; ?...假设Thread1获得GIL可以使用cpu,这时Thread1获得 互斥lock,Thread1可以改date数据(但并没有开始修改数据); (2)Thread1线程在修改date数据前发生了 i/o...lock,所以Thread2无法更改共享数据date,这时Thread2让出Gil , GIL再次发生竞争; (5)假设Thread1又抢到GIL,由于其有互斥Lock所以其可以继续修改共享数据data...,当Thread1修改完数据释放互斥lock,Thread2在获得GIL与lock后才可对data进行修改; 以上描述了 互斥和Gil的 一个关系 猜你喜欢: 1.python线程threading

1.7K31

C++ 多线程 ——

任何是一个线程都要使用互斥互斥访问任务队列,以避免多个线程同时访问任务队列以发生错乱。 在某一时刻,只有一个线程可以获取互斥,在释放互斥之前其他线程都不能获取该互斥。...C++ 语法 项目 内容 头文件 类型 std::mutex 用法 在C中,通过构造 std::mutex 的实例创建互斥元,调用成员函数 lock() 来锁定它,调用 unlock...() 来解锁不过一般推荐这种做法,标准C库提供了 std::lock_guard 和 unique_lock 类模板,都是 RAII 风格,它们是在定义时获得,在析构时释放。...它们的主要区别在于 unique_lock 机制更加灵活,可以再需要的时候进行 lock 或者 unlock 调用,非得是析构或者构造时。...假设线程T1获取互斥并且正在core1上运行时,此时线程T2也想要获取互斥(pthread_mutex_lock),但是由于T1正在使用互斥使得T2被阻塞。

1.3K60

CC++ Qt QThread 线程组件应用

::cout " << result << std::endl; return a.exec(); } QMutex 互斥同步线程: QMutex类是基于互斥量的线程同步...,该lock()锁定与unlock()解锁必须配对使用,线程保证线程间的互斥,利用线程能够保证临界资源的安全性....QMutexLocker会保护加锁区域,并自动实现互斥量的锁定和解锁操作,可以将其理解为是智能版的QMutex,该只需要在上方代码中稍加修改即可....() << std::endl; msleep(900); } } }; 互斥存在一个问题,每次只能有一个线程获得互斥量的权限,如果在程序中有多个线程来同时读取某个变量...,那么使用互斥量必须排队,效率上会大打折扣,基于QReadWriteLock读写模式进行代码段锁定,即可解决互斥存在的问题.

27710

CC++ Qt QThread 线程组件应用

::cout " << result << std::endl; return a.exec();}QMutex 互斥同步线程: QMutex类是基于互斥量的线程同步,该...lock()锁定与unlock()解锁必须配对使用,线程保证线程间的互斥,利用线程能够保证临界资源的安全性.线程解决的问题: 多个线程同时操作同一个全局变量,为了防止资源的无序覆盖现象,从而需要增加锁...QMutexLocker会保护加锁区域,并自动实现互斥量的锁定和解锁操作,可以将其理解为是智能版的QMutex,该只需要在上方代码中稍加修改即可....; msleep(900); } }};互斥存在一个问题,每次只能有一个线程获得互斥量的权限,如果在程序中有多个线程来同时读取某个变量,那么使用互斥量必须排队...,效率上会大打折扣,基于QReadWriteLock读写模式进行代码段锁定,即可解决互斥存在的问题.QReadWriteLock 读写同步线程: 该允许用户以同步读lockForRead()或同步写

45710

UNIX(多线程):15---死锁(Dead Lock)

如果你将某个mutex上锁了,却一直释放,另一个线程访问该保护的资源的时候,就会发生死锁,这种情况下使用lock_guard可以保证析构的时候能够释放,然而,当一个操作需要使用两个互斥元的时候,仅仅使用...); _mu2.unlock();}else { _mu2.lock(); _mu.lock();} 使用层次,将互斥包装一下,给锁定义一个层次的属性,每次按层次由高到低的顺序上锁...c++标准库中提供了std::lock()函数,能够保证将多个互斥同时上锁,std::lock(_mu, _mu2); 同时,lock_guard也需要做修改,因为互斥已经被上锁了,那么lock_guard... guard2(_mu); cout << msg << id << endl; } 不要在互斥保护的区域使用用户自定义的代码,因为用户的代码可能操作了其他的互斥。...f << msg << id << endl; } 如果想同时对多个互斥锁上锁,要使用std::lock()。 给锁定义顺序(使用层次,或者比较地址等),每次以同样的顺序进行上锁。

38110

C++ Qt开发:运用QThread多线程组件

在Qt中,QMutex提供了简单而有效的线程同步机制,其基本用法包括: 锁定Lock): 线程在访问共享资源之前,首先需要获取QMutex的,这通过调用lock()方法来实现。...该lock()锁定与unlock()解锁必须配对使用,线程保证线程间的互斥,利用线程能够保证临界资源的安全性。...其提供了两种锁定操作: 读取(Read Lock): 允许多个线程同时获取读取,用于并行读取共享数据。在没有写入的情况下,多个线程可以同时持有读取。...写入(Write Lock): 写入互斥的,当一个线程获取写入时,其他线程无法获取读取或写入。这确保了在写入数据时,不会有其他线程同时读取或写入。...互斥存在一个问题,每次只能有一个线程获得互斥量的权限,如果在程序中有多个线程来同时读取某个变量,那么使用互斥量必须排队,效率上会大打折扣,基于QReadWriteLock读写模式进行代码段锁定,即可解决互斥存在的问题

18010

GoF 23种经典的设计模式——单例模式

使用互斥或其他同步机制来保证只有一个线程可以执行初始化操作)。因此,可以使用静态局部变量来实现单例模式,而无需显式使用互斥。...class Singleton { private: static Singleton* instance; static std::mutex mutex; // 添加互斥...一种常见的线程安全的懒汉式实现方式是在 getInstance() 方法中使用双重检查锁定(Double-Checked Locking)和同步来确保只有一个线程创建实例。...双重检查锁定(Double-Checked Locking): 双重检查锁定是一种在懒汉式中使用的优化技术,用于在多线程环境下减少同步的开销。...在双重检查锁定中,首先检查实例是否已经被创建,如果没有,则使用同步对代码块进行加锁,然后再次检查实例是否已经被创建。

9210

Linux线程同步与互斥(一)

5.原子性:如果需要执行printf("hello world");访问临界资源(显示器),为了安全,加上互斥lock();printf();unlock();在加上锁到解锁的这段过程内,只能执行内的代码...); 返回值:成功返回0,失败返回错误号 在调用 pthread_mutex_lock的时可能会遇到以下情况: 1.互斥量处于未状态,该函数会将互斥锁定,同时返回成功。...2.发起函数调用时,其他线程已经锁定互斥量,或者存在其他线程同时申请互斥量,但没有竞争到互斥量,那么pthread_ lock调用会陷入阻塞(执行流被挂起),等待互斥量解锁。...2.调用了标准I/O库函数,标准I/O库的很多实现都以不可重入的方式使用全局数据结构。 3.可重入函数体内使用了静态的数据结构。 可重入的一些常见情况 1.不使用全局变量或静态变量。...2.不使用用malloc或者new开辟出的空间。 3.不调用不可重入函数。 4.返回静态或全局数据,所有数据都有函数的调用者提供。

1.4K30

C++111417中mutex系列区别

在规定的等待时间内,没有获取,线程不会一直阻塞,代码会继续执行recursive_mutexC++11递归,允许在同一个线程中同一个互斥量多次被 lock() ,用于可能被连续多次上锁(期间未解锁)...为了避免死锁,std::mutex.lock方法和std:mutex.unlock方法需要成对使用,如果一个函数中有很多出口,而互斥体对象又是需要在整个面数作用域被保护的资源,那么我们在编码时会因为忘记在某个出口处调用...这时可以通过RAII技术封装这两个接口,C++新标准也提为我们提供了类似的封装:互斥量管理C++版本作用lock_guardC++11基于作用于的互斥量管理,在需要对资源进行保护的小范围作用域内,应首先考虑使用...std::lock_guardunique_lockC++11unique_locklock_guard 的升级加强版,一个通用的互斥锁定包装器,它允许延迟锁定,限时深度锁定,递归锁定锁定所有权的转移以及与条件变量一起使用...多线程使用经验总结:减少使用次数,能不用尽量不用;明确的范围;减少使用粒度,尽量减少的作用的临界区代码范围。

1.1K20

C++并发编程(C++11到C++17)

一旦某个线程获取了互斥,任何其他线程都无法再获取互斥和共享;但是如果有某个线程获取到了共享,其他线程无法再获取到互斥,但是还有获取到共享。这里互斥使用和其他的互斥体接口和功能一样。...通用锁定算法 主要API image.png 要避免死锁,需要仔细的思考和设计业务逻辑。 有一个比较简单的原则可以避免死锁,即:对所有的进行排序,每次一定要按照顺序来获取,不允许乱序。...<< '\n'; } 这段代码中: 全局互斥体g_i_mutex用来保护全局变量g_i 这是一个设计为可以被多线程环境使用的方法。...因此需要通过互斥体来进行保护。这里没有调用lock方法,而是直接使用lock_guard来锁定互斥体。...在方法结束的时候,局部变量std::lock_guard lock会被销毁,它对互斥体的锁定也就解除了。 在多个线程中使用这个方法。

1.3K51
领券