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

为什么std::lock()在使用我自己的unique_lock对象时会导致无限循环?

std::lock()函数是C++标准库中的一个多线程同步函数,用于实现多个互斥量的原子性加锁操作。它接受一系列unique_lock对象作为参数,并尝试对这些互斥量进行加锁操作。

当使用自己的unique_lock对象作为std::lock()函数的参数时,如果存在死锁的情况,就会导致无限循环。这是因为std::lock()函数内部会对传入的unique_lock对象进行加锁操作,而如果自己的unique_lock对象已经被锁定,再次对其进行加锁操作就会导致死锁。

为了解决这个问题,可以使用std::adopt_lock参数来告诉std::lock()函数,传入的unique_lock对象已经被锁定,无需再次加锁。这样就可以避免无限循环的问题。

下面是一个示例代码:

代码语言:txt
复制
#include <iostream>
#include <thread>
#include <mutex>

std::mutex mutex1, mutex2;

void threadFunc()
{
    std::unique_lock<std::mutex> lock1(mutex1, std::defer_lock);
    std::unique_lock<std::mutex> lock2(mutex2, std::defer_lock);
    
    std::lock(lock1, lock2);
    
    // 执行一些操作
    
    lock1.unlock();
    lock2.unlock();
    
    // 继续执行其他操作
}

int main()
{
    std::thread t(threadFunc);
    
    // 执行一些操作
    
    t.join();
    
    return 0;
}

在上面的示例代码中,我们使用std::defer_lock参数来延迟unique_lock对象的加锁操作,然后再调用std::lock()函数对这些unique_lock对象进行加锁。这样就可以避免无限循环的问题。

需要注意的是,std::lock()函数会按照参数列表中unique_lock对象的顺序进行加锁操作,所以在使用std::lock()函数时,需要保证传入的unique_lock对象的顺序是一致的,以避免死锁的发生。

对于这个问题,腾讯云没有直接相关的产品和产品介绍链接地址。

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

相关·内容

使用条件变量坑你知道吗

——《认知破局》 想必大家开发过程中都会用到多线程,用到多线程基本上都会用到条件变量,你理解条件变量只是简单wait和notify吗,最近工作中看同事也都只是简单使用wait和notify,导致项目出现...条件变量如何使用? 如何解决条件变量信号丢失问题? 如何解决条件变量虚假唤醒问题? 条件变量为什么一定要和锁配合使用? 1 什么是条件变量?...条件变量多线程中很常用,在有名生产者和消费者问题中,消费者如何知道生成者是否生产出了可以消费产品,通过while循环不停去判断是否有可消费产品?...C++中其实有更好封装,只需要调用wait函数时,参数中直接添加附加条件就好了,内部已经做好了while循环判断,直接使用即可,见代码: std::mutex mutex; std::condition_variable...4 为什么条件变量需要和锁配合使用为什么叫条件变量呢? 因为内部是通过判断及修改某个全局变量来决定线程阻塞与唤醒,多线程操作同一个变量肯定需要加锁来使得线程安全。

2.3K30

C++11互斥包装器

C++多线程中会经常用到mutex,使用时候lock后,有时候会忘记使用unlock进行解锁造成死锁,或者lock和unlock之间代码异常跳出,导致程序无法执行到unlock造成死锁,因此C...++11中引入互斥体包装器,互斥体包装器为互斥提供了便利RAII风格机制,本质上就是包装器构造函数中加锁,析构函数中解锁,将加锁和解锁操作与对象生存期深度绑定,防止使用mutex加锁(lock...RAII 保证资源能够用于任何会访问该对象函数(资源可用性是一种类不变式,这会消除冗余运行时测试)。它也保证对象自己生存期结束时会以获取顺序逆序释放它控制所有资源。...//流程1结束 // g_i_mutex 锁离开作用域时自动释放 } 如上例所述,如果流程1过程特别长,而且不涉及g_i操作,如果使用lock_guard的话会导致g_i上锁时间特别长...因此,针对这种应用场景,我们应该使用unique_lock对g_i进行互斥锁管理,我们可以流程1开始处,进行手动解锁,提前释放g_i所有权,提高程序效率。

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

    detach():传统多线程,主线程要等待子线程执行完毕,然后自己再最后退出, detach分离,也就是主线程和子线程不汇合了,各自独立执行,主线程执行完了,不影响子线程。为什么引入detach?...它不存这种因为多个线层中,因为锁顺序问题导致死锁风险问题 std::lock() 如果互斥量中有一个没锁住,它就在那里等着。其情况就是多个锁要么都锁住,要么都没锁住。...; 使用条件变量std::condition_variable时需要使用std::unique_lock而不能使用std::lock_guard。...unique_lock所有权传递 std::unique_lock example(my_mutex); //example可以把自己mutex所有权转移给其他unique_lock...简单说就是,当std::condition_variable对象某个wait函数被调用时候,它使用std::unique_lock(通过std::mutex)来锁住当前线程。

    5K41

    C++ 条件变量使用详解

    细节说明 条件变量中只能使用std::unique_lock说明 unique_locklock_guard都是管理锁辅助类工具,都是RAII风格;它们是定义时获得锁...; wait 导致当前线程阻塞直至条件变量被通知,或虚假唤醒发生,可选地循环直至满足某谓词。...这就是条件变量只能和unique_lock一起使用原因,否则当前线程一直占有锁,线程被阻塞。...虚假唤醒 正常情况下,wait类型函数返回时要不是因为被唤醒,要不是因为超时才返回,但是实际中发现,因此操作系统原因,wait类型不满足条件时,它也会返回,这就导致了虚假唤醒。...该问题描述了共享固定大小缓冲区两个进程/线程——即所谓“生产者”和“消费者”,实际运行时会发生问题。 生产者主要作用是生成一定量数据放到缓冲区中,然后重复此过程。

    2.7K11

    【C++】C++11 线程库

    我们还是以 ++g_val 操作为例,和一般 ++ 操作不同,CAS 会额外使用一个寄存器来保存讲寄存器中 g_val 修改之前值 (预期原值),并且将修改之后值 (新值) 写回到内存时会重新取出内存中...但单纯放弃写入会导致可能当前 ++ 操作执行了但是 g_val 值并不变;所以 C++ 对 CAS 操作进行了封装,即在 CAS 外面套了一层 while 循环,当新值成功写入时跳出循环,当新值写入失败时重新执行之前取数据...具体来说,condition_variable 主要由以下两个成员函数组成: void wait(std::unique_lock& lock): 该函数会使当前线程阻塞,直到另一个线程调用...调用该函数时需要传递一个已经加锁 unique_lock 对象,函数内部会自动释放锁。当该函数返回时,锁会再次被该线程持有。...具体来说,一般会创建一个 mutex 对象和一个 condition_variable 对象,并在等待某个条件时使用 unique_lock 对象进行加锁和解锁。

    47640

    17个C++编程常见错误及其解决方案

    为了让自己编程之路更加顺畅,也为了持续精进技艺,想借此机会汇总分享那些常被我们无意间忽视却又导致警告编程小细节,以此作为对未来自我警示和提升。1....(m1); std::unique_lock lck2(m2, std::defer_lock); while (!...无符号整数循环条件错误错误示例: 循环使用无符号整数作为递减计数器,当期望循环结束时计数器为0,但由于无符号整数特性导致无法正确终止循环。...}解决方法: 循环体内避免对用于迭代对象进行修改,若必须删除或移动元素,可选择复制迭代器或使用其它合适数据结构操作方法。...但依据C++标准,全局对象初始化顺序未严格规定,尤其不同编译器或复杂项目中,可能导致Service使用未完全初始化Database对象,引发未预期行为。

    81110

    【C++】C++11之线程库

    一、thread类 C++11 之前,涉及到多线程问题,都是和平台相关,比如 windows 和 linux 下各有自己接 口,这使得代码可移植性比较差 。...构造 ( 或移动(move)赋值 ) 时, unique_lock 对象需要传递一个 Mutex 对象作为它参数,新创建unique_lock 对象负责传入 Mutex 对象上锁和解锁操作...使用以上类型互斥量实例化 unique_lock 对象时,自动调用构造函数上锁, unique_lock 对象销毁时自动调用析构函数解 锁,可以很方便防止死锁问题。...使得进程避免因为不满足条件而一直循环判断,浪费资源。  需要注意是: wait接口参数是unique_lock类型。 有人会好奇为什么需要传一个锁进来呢?...原因出在这里:  因此我们只需要把t1时循环条件<= 改成 < 即可,这样,100时候进不去循环了,自然后面的操作也就不会执行了。

    40980

    线程同步-The Boost C++ Libraries

    这将导致线程等待,直到拥有互斥锁线程完成处理并释放其对该互斥锁所有权为止。 示例44.7使用类型为boost::mutex全局互斥锁,称为互斥锁。...thread()函数通过调用lock()获得此对象所有权。 这是函数写入标准输出流之前完成。 写入消息后,将通过调用unlock()释放所有权。...每个线程计数到5,并在for循环每次迭代中将一条消息写入标准输出流。 由于std::cout是线程共享全局对象,因此访问必须同步。 否则,消息可能会混淆。...两种变体仍然循环中向标准输出流写入五个数字,但是现在它们使用类boost::unique_lock来锁定互斥体。...fill()使用unlock()成员函数释放互斥量,然后等待一秒钟。与前面的示例不同,for循环末尾调用wait(),以确保容器中至少有一个随机数被print()或count()访问之前。

    83410

    C++并发编程 - 互斥锁(lock_guard和unqiue_lock

    主要有以下优势: 无需考虑互斥量初始化和销毁,构造和析构函数中管理,无需使用者操心。 采用RAII对互斥量进行了不同封装,提供了更方便上锁机制。...lock_guard lock_guard功能与std::mutexlock与ublock功能相同。不同是,lock_guard析构时会自动解锁,使用时无须unlock。...lock_guard&) = delete; private: _Mutex& _MyMutex; }; 从构造与析构可以看出,lock_guard对象创建时会主动调用lock()加锁,销毁时会主动调用...std::unique_lock 可以构造时传递第二个参数用于管理互斥量,且能传递不同域中互斥量所有权。...另外通过观察「unique_lock」几种构造,不同情况可使用对应构造创建对象: unique_lock(mutex) 传递未被使用mutex,通过。会上锁,无法获得锁时会阻塞。

    59420

    C++写高性能任务流线程池(万字详解!全面解析!)

    可以参考下图: 但是Work Steal机制也可能成为线程池累赘,为什么这么说呢?明明感觉他很完美啊!...换句话说,只扫门前雪:线程只关注自己邻居任务组可不可以拿任务,当拿不到时候(就是没任务时候)再去其他地方取任务,这样就解决了大量循环问题。...考虑到任务流工作需要,我们写入任务时候,不免有时会传入大量任务,甚至远超出程序承载力,那么如何提升程序负载能力呢,大家有学过python应该知道python中迭代器,当然不止python...我们可以使用完美转换来优化,利用std::move和std::forward来进行所有权移交 此处std::move和std::forward,可以看看这篇文章,讲很好 拒绝机制 注意:该机制本线程池中并未实现...在前面的内容中,我们也都是通过for循环方式,将一堆任务放到线程池中执行。考虑下面几个问题: 想等这一批任务执行结束,再执行其他任务,怎么办?

    25520

    C++ std::unique_lock 用法

    1.创建 std::unique_lock 对象 std::unique_lock lock(mutex); // 创建 std::unique_lock 并关联互斥锁 mutex...你可以构造函数中传入一个互斥锁(std::mutex 或其它互斥锁类型)来创建 std::unique_lock 对象,并且会在构造时获取互斥锁所有权。...创建对象,当其生命周期结束时(通常是大括号作用域结束时),会自动解锁互斥锁,以确保互斥锁在不再需要时被释放。...创建 std::unique_lock 对象时,传入互斥锁但不加锁: std::unique_lock lock(mutex, std::defer_lock); 需要时手动加锁...多数情况下,推荐使用 std::unique_lock 而不是直接操作互斥锁,因为它能够自动管理锁生命周期,减少了出错机会。

    1.4K20

    为什么说智能指针是解决问题“神器”?

    一、为什么需要使用智能指针 (一)内存泄漏 C++堆上申请内存后,需要手动对内存进行释放。代码初创者可能会注意内存释放,但随着代码协作者加入,或者随着代码日趋复杂,很难保证内存都被正确释放。...::string event){ std::unique_lock lock(mutex_); this->count_++;} 使用ReportClass代码如下...由于shared_ptr是通过引用计数来管理原生指针,那么最大问题就是循环引用(比如a对象持有b对象,b对象持有a对象),这样必然会导致内存泄露。...使用智能指针托管对象,尽量不要在再使用原生指针 很多开发同学(包括在内)最开始使用智能指针时候,对同一个对象会混用智能指针和原生指针,导致程序异常。...std::unique_lock lock(mutex_); this->count_++;} 并且多个线程使用时候,由于采用shared_ptr管理,因此只要有shared_ptr

    99820

    【C++】C++11线程库 和 C++IO流

    因为线程条件变量中等待和被唤醒时候,需要释放锁和加锁,而lock_guard只有RAII,无法实现这样主动加锁和释放锁功能,所以条件变量wait时候必须使用unique_lock。...条件变量是配合互斥锁来进行使用,所以多线程访问条件变量操作本身就是线程不安全,所以使用条件变量之前需要加锁,并且条件变量wait接口只允许使用unique_lock,有两点原因,一是unique_lock...很多在线OJ题目中有很多IO类型题,这些题往往都要求循环cin输入,我们知道cin返回对象是一个istream类对象,那为什么istream类对象能够做逻辑判断呢?...要想知道原因,需要先知道什么是二进制写入,二进制写入你可以简单理解为将数据二进制表示形式原模原样写入到文件中,例如某个指针二进制表示形式为0x0032447b3a(自己),那二进制写入时,...对象析构时,ptr指针相同并且都是野指针,所以就会出现析构野指针情况,这就会导致程序异常退出。

    29020

    C++多线程unique_lock详解

    同样,unique_lock也是一个类模板,但是比起lock_guard,它有自己成员函数来更加灵活进行锁操作。        ...使用方式和lock_guard一样,不同unique_lock有不一样参数和成员函数。...一般用来搭配unique_lock成员函数去使用。下面就列举defer_lock和一些unique_lock成员函数使用方法。        ...当使用了defer_lock参数时,创建了unique_lock对象时就不会自动加锁,那么就需要借助lock这个成员函数来进行手动加锁,当然也有unlock来手动解锁。...m->unlock(); } } unique_lock所有权传递        对越unique_lock对象来说,一个对象只能和一个mutex锁唯一对应,不能存在一对多或者多对一情况

    20.3K62
    领券