在运维工作中,Linux的锁有什么?

news/2025/2/23 12:32:56/文章来源:https://www.cnblogs.com/huangjiabobk/p/18731991

在 Linux 系统中,锁是一种重要的同步机制,用于协调多个进程或线程对共享资源的访问,防止数据竞争和不一致。在运维工作中,了解锁的类型和使用场景可以帮助优化系统性能、排查死锁问题以及确保系统的稳定性。以下是 Linux 中常见的锁类型及其详细说明:

1. 锁的分类

Linux 中的锁可以按照作用范围和实现机制分为以下几类:

1.1 按作用范围分类
  • 进程级锁:用于协调不同进程之间的资源访问。
  • 线程级锁:用于协调同一进程内不同线程之间的资源访问。
1.2 按实现机制分类
  • 内核态锁:由内核直接实现,用于内核代码中的同步。
  • 用户态锁:由用户空间程序实现,依赖内核提供的系统调用。
2. 常见的锁类型
2.1 内核态锁

内核态锁主要用于内核代码中的同步,防止多个 CPU 核心或中断上下文同时访问共享资源。

2.1.1 互斥锁(Mutex)

  • 特点:一次只能被一个进程或线程持有。

  • 用途:保护临界区,确保同一时间只有一个线程可以访问共享资源。

  • 示例

    mutex_lock(&my_mutex);
    // 临界区代码
    mutex_unlock(&my_mutex);
    

2.1.2 自旋锁(Spinlock)

  • 特点:当锁被占用时,线程会不断循环等待锁释放,而不是进入睡眠状态。

  • 用途:适用于锁持有时间非常短的场景,避免上下文切换开销。

  • 示例

    spin_lock(&my_spinlock);
    // 临界区代码
    spin_unlock(&my_spinlock);
    

2.1.3 读写锁(RWLock)

  • 特点:允许多个读操作同时进行,但写操作需要独占锁。

  • 用途:适用于读多写少的场景,提高并发性能。

  • 示例

    read_lock(&my_rwlock);
    // 读操作
    read_unlock(&my_rwlock);write_lock(&my_rwlock);
    // 写操作
    write_unlock(&my_rwlock);
    

2.1.4 顺序锁(Seqlock)

  • 特点:一种轻量级锁,用于保护数据结构,允许读者在写者修改数据时继续读取旧值。

  • 用途:适用于读多写少的场景,减少锁的开销。

  • 示例

    unsigned seq;
    do {seq = read_seqbegin(&my_seqlock);// 读取数据
    } while (read_seqretry(&my_seqlock, seq));write_seqlock(&my_seqlock);
    // 修改数据
    write_sequnlock(&my_seqlock);
    

2.1.5 完全公平锁(Fair Lock)

  • 特点:确保线程按请求顺序获取锁,避免饥饿现象。
  • 用途:适用于对公平性要求较高的场景。

2.1.6 原子操作

  • 特点:通过硬件指令保证操作的原子性,无需锁机制。

  • 用途:适用于简单的整数或指针操作。

  • 示例

    atomic_add(1, &my_atomic_var);
    
2.2 用户态锁

用户态锁主要用于用户空间程序中的同步,依赖内核提供的系统调用。

2.2.1 POSIX 互斥锁(pthread_mutex)

  • 特点:由 POSIX 标准定义,用于线程间的同步。

  • 用途:保护临界区,确保同一时间只有一个线程可以访问共享资源。

  • 示例

    pthread_mutex_lock(&my_mutex);
    // 临界区代码
    pthread_mutex_unlock(&my_mutex);
    

2.2.2 POSIX 读写锁(pthread_rwlock)

  • 特点:允许多个读操作同时进行,但写操作需要独占锁。

  • 用途:适用于读多写少的场景,提高并发性能。

  • 示例

    pthread_rwlock_rdlock(&my_rwlock);
    // 读操作
    pthread_rwlock_unlock(&my_rwlock);pthread_rwlock_wrlock(&my_rwlock);
    // 写操作
    pthread_rwlock_unlock(&my_rwlock);
    

2.2.3 文件锁(fcntl 锁)

  • 特点:用于进程间的同步,通过文件描述符实现。

  • 用途:防止多个进程同时写入同一个文件。

  • 示例

    struct flock fl;
    fl.l_type = F_WRLCK;  // 设置为写锁
    fl.l_whence = SEEK_SET;
    fl.l_start = 0;
    fl.l_len = 0;fcntl(fd, F_SETLK, &fl);  // 设置锁
    

2.2.4 信号量(Semaphore)

  • 特点:一种计数器,用于控制多个进程对共享资源的访问。

  • 用途:适用于需要限制资源访问数量的场景。

  • 示例

    sem_wait(&my_semaphore);
    // 临界区代码
    sem_post(&my_semaphore);
    
3. 锁的使用场景与注意事项
3.1 锁的使用场景
  • 多线程程序:保护共享变量或数据结构。
  • 多进程程序:防止多个进程同时写入同一个文件或资源。
  • 内核模块:保护内核数据结构,防止并发访问导致的数据不一致。
3.2 注意事项
  • 死锁:多个线程或进程相互等待对方持有的锁,导致无法继续执行。
    • 解决方案:避免嵌套锁,使用超时机制或锁顺序。
  • 锁竞争:多个线程频繁竞争同一把锁,导致性能下降。
    • 解决方案:减少锁的粒度,使用读写锁或无锁编程。
  • 锁的开销:锁的获取和释放会带来性能开销,尤其是自旋锁。
    • 解决方案:合理选择锁的类型,避免过度使用锁。
4. 锁的监控与优化

在运维工作中,可以通过以下方式监控和优化锁的使用:

  • 监控锁的使用情况
    • 使用 perfstrace 工具分析锁的获取和释放时间。
    • 检查系统日志,查找锁相关的错误或警告信息。
  • 优化锁的使用
    • 减少锁的持有时间,避免长时间占用锁。
    • 使用更细粒度的锁,减少锁竞争。
    • 在可能的情况下,使用无锁编程技术。
5. 锁的调试工具
  • perf:性能分析工具,可以分析锁的争用情况。

    perf record -e sched:sched_stat_runtime -a -g
    perf report
    
  • futex:用于调试用户态锁的工具。

    strace -e futex ./my_program
    
6. 我的总结

综上所述,Linux 中的锁是并发编程和系统同步的重要机制,主要包括内核态锁(如互斥锁、自旋锁、读写锁)和用户态锁(如 POSIX 锁、文件锁、信号量)。锁的合理使用可以提高系统的并发性能,但不当使用可能导致死锁或性能问题。在运维工作中,运维人员需要了解锁的类型和使用场景,掌握锁的监控和优化方法,以便快速定位和解决锁相关的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/888334.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实操让Deepseek根据本地知识库进行回答

之前写了一篇本地电脑部署Deepseek的文章,有些朋友问到如何给本地的Deepseek添加知识库,于是我又找时间学习了下。现在把我的实操过程分享一下。这个是本地部署Deepseek的教程:https://www.cnblogs.com/LaiYun/p/18695293下载安装Cherry-Studio部署完本地Deepseek后就使用Ch…

[Log4j/日志系统] Log4j2.xml 配置详解

Configuration 定义整个配置文件的根元素,整个配置信息都在这个标签内。 Demodemo<?xml version="1.0" encoding="UTF-8" ?> <!--monitorInterval属性值(秒数)为一个非零值来让Log4j每隔指定的秒数来重新读取配置文件,可以用来动态应用Log4…

delphi 漂亮的开关按钮 与 web ui 一样漂亮的开关按钮 djToggleSwitchButton

效果图 在 delphi 界 找个漂亮的开关按钮,不容易,ddj 为您提供了漂亮的开关按钮,以下是 效果图说明判断开关 双击这个 开关按钮,在 onClick事件里 写逻辑代码就可,如: procedure TFormMain.djToggleSwitch1Click(Sender: TObject); beginif djToggleSwitch1.StateOn then…

ollama本地大模型的安装与使用

ollama本地大模型的安装与使用1、定义 Ollama:‌是一个开源的大型语言模型(LLM)服务工具,旨在简化在本地运行大语言模型的过程,降低使用大语言模型的门槛‌。 2、安装 https://ollama.com/download 根据自己的电脑系统来选择安装不同的版本,默认安装就可以解决。3、安装成功…

易语言 —— 第一篇

易语言第一课 - 界面熟悉与“你好世界!” 1. 安装易语言集成开发环境并新建一个应用程序 在安装好易语言集成开发环境后,首先需要新建一个应用程序。具体步骤如下:打开易语言集成开发环境。 点击菜单栏中的“文件” -> “新建” -> “应用程序”。2. 界面的简单介绍 易…

MyBatis-Plus 的自动填充 —— 值为null

MyBatis-Plus 的自动填充 MyBatis-Plus 提供的字段自动填充功能是一种非常实用的特性,它能够在插入或更新数据库记录时自动填充一些公共字段,如创建时间(createTime)、更新时间(updateTime)、创建人(createBy)、更新人(updateBy)等。这一功能极大地简化了开发过程,减…

[Jaav SE/程序生命周期] 优雅的Java应用程序的启停钩子框架

序了解 spring 生态及框架的 java er 都知道,spring 应用的生命周期管理及配套接口较为优雅、可扩展。但脱离 spring 的 java 应用程序,如何优雅地启停、管理程序的生命周期呢?(以便应用程序在我们需要的运行阶段中进行相应的动作)概述:Java普通应用程序的启停钩子框架 前…

迈金C416码表体验

之前一直在用黑鸟单车和小米健康记录骑行数据, 后来又发现strava和keep的骑行分享功能做的比较好. 于是使用的运动app就越来越多, 骑行时带着手机的同时还要开好几个app太麻烦了, 同时也想给车上加一个速度显示器, 由此考虑入一个码表.对功能要求不高, 最主要的需求是gps和速度…

ASP.NET Core Swagger 汉化

在wwwroot文件夹添加汉化的JS文件const translations = {"Failed to load API definition": "API定义加载失败","Errors": "错误信息","Hide": "隐藏","Fetch error": "获取错误","Inte…

Svelte 最新中文文档教程(17)—— 生命周期钩子

前言 Svelte,一个语法简洁、入门容易,面向未来的前端框架。从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1:Svelte 以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非常适合构…