当前位置: 首页 > news >正文

面试题及解答:锁

一、锁基础与核心概念

  1. 锁的作用与类型

    • 作用:保护共享资源,防止多线程并发访问导致数据竞争和不一致。
    • 类型
      • 互斥锁(Mutex):同一时间仅一个线程可访问资源(如 std::mutexQMutex)。
      • 读写锁(ReadWriteLock):允许多个读线程或一个写线程(如 QReadWriteLock)。
      • 自旋锁(SpinLock):忙等待锁,适用于短临界区(无标准库实现,需手动或第三方库)。
      • 信号量(Semaphore):控制多资源并发访问(如 QSemaphore)。
  2. 死锁的产生与避免

    • 产生条件:循环等待、互斥、不可抢占、持有并等待。
    • 避免策略
      • 固定加锁顺序:所有线程按相同顺序获取锁(例:先锁A再锁B)。
      • 超时机制:使用 try_lock_for() 避免永久阻塞。
      • 减小锁粒度:仅保护必要数据,缩短持有时间。
      • 锁分解:将大锁拆分为多个小锁。

二、C++锁机制(STL)

1. std::lock_guard vs std::unique_lock
特性std::lock_guardstd::unique_lock
灵活性构造时加锁,析构解锁支持手动加/解锁和延迟加锁
所有权不可转移可转移(如 std::move
性能更高(无额外开销)稍低(功能更多)
适用场景简单临界区需灵活控制的复杂场景

代码示例

// lock_guard 示例
std::mutex mtx;
{std::lock_guard<std::mutex> lock(mtx); // 自动加锁// 临界区操作
} // 自动解锁// unique_lock 延迟加锁
std::unique_lock<std::mutex> ulock(mtx, std::defer_lock);
ulock.lock(); // 手动加锁
ulock.unlock(); // 手动解锁
2. adopt_lock/defer_lock/try_to_lock 用法
  • std::adopt_lock:假定锁已被当前线程锁定,构造时不加锁。
    mtx.lock();
    std::lock_guard<std::mutex> lock(mtx, std::adopt_lock); // 直接接管已加锁的mtx
    
  • std::defer_lock:构造时不加锁,后续手动控制。
  • std::try_to_lock:尝试非阻塞加锁,失败不阻塞。

三、Qt锁机制与多线程同步

1. Qt多线程同步工具
工具用途示例
QMutex基础互斥锁QMutexLocker locker(&mutex);
QReadWriteLock读写分离锁(多读单写)QReadLocker rlock(&rwLock);
QSemaphore控制多资源访问(如生产者-消费者)sem.acquire(); sem.release();

生产者-消费者示例

QSemaphore freeSpace(10); // 缓冲区大小=10
QSemaphore usedSpace(0);void Producer::run() {freeSpace.acquire(); // 申请空闲位// 生产数据usedSpace.release(); // 增加已使用位
}
void Consumer::run() {usedSpace.acquire(); // 消费数据freeSpace.release();
}
2. 信号槽的线程安全控制
  • 连接类型
    • Qt::DirectConnection:槽函数在发送者线程执行(跨线程危险)。
    • Qt::QueuedConnection:槽函数在接收者线程执行(跨线程安全)。
connect(sender, &Sender::signal, receiver, &Receiver::slot, Qt::QueuedConnection);

四、死锁场景与解决方案

面试题:手写一个线程安全的单例模式(双检锁)
class Singleton {
public:static Singleton* getInstance() {if (instance == nullptr) { // 第一次检查std::lock_guard<std::mutex> lock(mtx);if (instance == nullptr) { // 第二次检查(避免重复创建)instance = new Singleton();}}return instance;}
private:static Singleton* instance;static std::mutex mtx;
};
// 初始化静态成员
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;

关键点:双检锁减少锁竞争,保证线程安全。


五、线程安全队列实现(C++11版)

#include <queue>
#include <mutex>
#include <condition_variable>template<typename T>
class SafeQueue {std::queue<T> queue;std::mutex mtx;std::condition_variable cv;
public:void push(T item) {std::lock_guard<std::mutex> lock(mtx);queue.push(item);cv.notify_one(); // 唤醒一个等待线程}T pop() {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [this]{ return !queue.empty(); }); // 避免虚假唤醒T val = queue.front();queue.pop();return val;}
};

核心机制

  • 条件变量:空队列时阻塞 pop() 线程,直到 push() 唤醒。
  • unique_lock:配合 cv.wait() 需手动解锁需求。

总结与面试技巧

  1. 基础必考
    • 手写双检锁单例、线程安全队列。
    • 解释 lock_guardunique_lock 区别。
  2. 高阶考点
    • Qt信号槽线程控制(QueuedConnection)。
    • 死锁规避策略(顺序加锁、超时机制)。
  3. 答题技巧
    • 强调边界处理:如空队列 pop()、锁未释放场景。
    • 结合Qt特性:如 “在Qt中优先用 QMutexLocker 而非手动 lock/unlock”。
    • 性能对比:读写锁 vs 互斥锁在高读场景下的优势。

所有代码需注意异常安全(如锁的RAII管理)和跨平台兼容(Qt锁 vs STL锁)。

http://www.dtcms.com/a/308980.html

相关文章:

  • 字母异位词分组(每天刷力扣hot100系列)
  • 即时通讯系统项目面试可能的考点
  • 对git 熟悉时,常用操作
  • QT收费情况
  • 谷歌V3插件热更新
  • 类与对象(上),咕咕咕
  • 【Node】nvm在windows系统无管理员权限切换node版本
  • 20250731在荣品的PRO-RK3566开发板的Android13下跑通敦泰的FT8206触控芯片
  • 【Java EE初阶 --- 网络原理】网络层---IP协议,数据链路层---以太网协议
  • OpenCV学习day2
  • YodA数据集的格式化(二)
  • MySQL 8.0 OCP 1Z0-908 题目解析(39)
  • 项目中如何追踪项目进度,避免项目延期如何追踪项目进度
  • 尚硅谷尚庭公寓学习笔记
  • 《P2910 [USACO08OPEN] Clear And Present Danger S》
  • JVM之【Java虚拟机概述】
  • uniapp中uview组件中u-input格式化后赋值踩坑
  • 网站技术攻坚与Bug围剿手记
  • nodejs——在Express中使用Session认证
  • 基于 AXI-Lite 实现可扩展的硬件函数 RPC 框架(附完整源码)
  • graph attention network
  • Sklearn 机器学习 文本数据 计数向量化加入停用词
  • Spring Boot 项目问题:Web server failed to start. Port 5566 was already in use.
  • Linux应用开发基础知识——Makefile初级教程(九)
  • 订单识别与发票识别结合的技术实现方案
  • 最新PS 2025安装包下载与安装教程(Adobe Photoshop 2025 )
  • Java客户端连接Redis
  • langchain--2--invoke、batch、stream、ainvoke、abatch、astream
  • 51c自动驾驶~合集12
  • Python脚本批量将usdz文件转为glb文件