《Linux性能优化实战》学习笔记 Day04

简介: 《Linux性能优化实战》学习笔记 Day04

06 | 锁:如何根据业务场景选择合适的锁?

原文摘抄

当你无法判断锁住的代码会执行多久时,应该首选互斥锁,互斥锁是一种独占锁。

如果你能确定被锁住的代码执行时间很短,就应该用自旋锁取代互斥锁。

对于 99% 的线程级互斥锁而言,阻塞都是由操作系统内核实现的(比如 Linux 下它通常由内核提供的信号量实现)

自旋锁比互斥锁快得多,因为它通过 CPU 提供的 CAS 函数(全称 Compare And Swap),在用户态代码中完成加锁与解锁操作。

CAS 忙等待

while (true) {
  //因为判断lock变量的值比CAS操作更快,所以先判断lock再调用CAS效率更高
  if (lock == 0 &&  CAS(lock, 0, pid) == 1) return;
  if (CPU_count > 1 ) { //如果是多核CPU,“忙等待”才有意义
      for (n = 1; n < 2048; n <<= 1) {//pause的时间,应当越来越长
        for (i = 0; i < n; i++) pause();//CPU专为自旋锁设计了pause指令
        if (lock == 0 && CAS(lock, 0, pid)) return;//pause后再尝试获取锁
      }
  }
  sched_yield();//单核CPU,或者长时间不能获取到锁,应主动休眠,让出CPU
}

这是两种最基本的处理方式,更高级别的锁都会选择其中一种来实现,比如读写锁就既可以基于互斥锁实现,也可以基于自旋锁实现。

如果你能够明确区分出读和写两种场景,可以选择读写锁。

因此,读写锁真正发挥优势的场景,必然是读多写少的场景,否则读锁将很难并发持有。

用队列把请求锁的线程排队,按照先来后到的顺序加锁即可,当然读线程仍然可以并发,只不过不能插队到写线程之前。

乐观锁全程并没有加锁,所以它也叫无锁编程。

乐观锁虽然去除了锁操作,但是一旦发生冲突,重试的成本非常高。所以,只有在冲突概率非常低,且加锁成本较高时,才考虑使用乐观锁。

读写锁是有倾向性的,读优先锁很高效,但容易让写线程饿死,而写优先锁会优先服务写线程,但对读线程亲和性差一些。

协程自旋锁

Go里的自旋锁需要自己实现,方便协程调度。协程使用自旋锁的时候,这是spinLock 的Lock方法

for !atomic.CompareAndSwapUint32(sl, 0, 1) {
    runtime.Gosched()
}
其中runtime.Gosched,是把阻塞的协程调度出去,这样调度器可以执行其他协程。

心得体会

锁用操作系统封装好的接口调用,会好方便。但是很多场景都是要封装高级锁的。

工作体验

CAS相对用的较少,没啥特别高的并发量,锁还是方便的。23333。

可能在分布式集群里,分布式锁比单机的锁用的要多一点。

就怕锁都不知道要锁的。

目录
相关文章
|
8天前
|
存储 运维 Shell
运维.Linux.bash学习笔记.数组及其使用
运维.Linux.bash学习笔记.数组及其使用
14 0
|
1月前
|
存储 网络协议 Ubuntu
【Linux开发实战指南】基于UDP协议的即时聊天室:快速构建登陆、聊天与退出功能
UDP 是一种无连接的、不可靠的传输层协议,位于IP协议之上。它提供了最基本的数据传输服务,不保证数据包的顺序、可靠到达或无重复。与TCP(传输控制协议)相比,UDP具有较低的传输延迟,因为省去了建立连接和确认接收等过程,适用于对实时性要求较高、但能容忍一定数据丢失的场景,如在线视频、语音通话、DNS查询等。 链表 链表是一种动态数据结构,用于存储一系列元素(节点),每个节点包含数据字段和指向下一个节点的引用(指针)。链表分为单向链表、双向链表和循环链表等类型。与数组相比,链表在插入和删除操作上更为高效,因为它不需要移动元素,只需修改节点间的指针即可。但访问链表中的元素不如数组直接,通常需要从
113 2
|
2月前
|
消息中间件 运维 监控
Linux命令lsipc:深入解析与实战应用
`lsipc` (通常指 `ipcs`) 是Linux命令,用于查看系统中的IPC资源,包括消息队列、信号量和共享内存。它显示详细信息,支持过滤,并且需要相应权限。示例用法:显示共享内存(`-m`)、查询消息队列(`-q -i ID`)、查看关联进程(`-m -p`)。注意权限、操作影响及定期监控。结合`ipcrm`等工具可进行更深入管理。
|
3月前
|
运维 Oracle 容灾
Oracle dataguard 容灾技术实战(笔记),教你一种更清晰的Linux运维架构
Oracle dataguard 容灾技术实战(笔记),教你一种更清晰的Linux运维架构
|
1天前
|
Linux
Linux源码阅读笔记19-插入删除模块实战
Linux源码阅读笔记19-插入删除模块实战
|
4天前
|
Linux 调度
Linux源码阅读笔记05-进程优先级与调度策略-实战分析
Linux源码阅读笔记05-进程优先级与调度策略-实战分析
|
10天前
|
关系型数据库 Linux 网络安全
"Linux系统实战:从零开始部署Apache+PHP Web项目,轻松搭建您的在线应用"
【8月更文挑战第9天】Linux作为服务器操作系统,凭借其稳定性和安全性成为部署Web项目的优选平台。本文以Apache Web服务器和PHP项目为例,介绍部署流程。首先,通过包管理器安装Apache与PHP;接着创建项目目录,并上传项目文件至该目录;根据需要配置Apache虚拟主机;最后重启Apache服务并测试项目。确保防火墙允许HTTP流量,正确配置数据库连接,并定期更新系统以维持安全。随着项目复杂度提升,进一步学习高级配置将变得必要。
22 0
|
1月前
|
缓存 监控 网络协议
Linux系统性能优化
Linux系统的性能是指操作系统完成任务的有效性、稳定性和响应速度。
38 1
|
1月前
|
SQL 自然语言处理 网络协议
【Linux开发实战指南】基于TCP、进程数据结构与SQL数据库:构建在线云词典系统(含注册、登录、查询、历史记录管理功能及源码分享)
TCP(Transmission Control Protocol)连接是互联网上最常用的一种面向连接、可靠的、基于字节流的传输层通信协议。建立TCP连接需要经过著名的“三次握手”过程: 1. SYN(同步序列编号):客户端发送一个SYN包给服务器,并进入SYN_SEND状态,等待服务器确认。 2. SYN-ACK:服务器收到SYN包后,回应一个SYN-ACK(SYN+ACKnowledgment)包,告诉客户端其接收到了请求,并同意建立连接,此时服务器进入SYN_RECV状态。 3. ACK(确认字符):客户端收到服务器的SYN-ACK包后,发送一个ACK包给服务器,确认收到了服务器的确
158 1
|
2月前
|
NoSQL Linux 程序员
Linux objdump命令:深入解析与实战应用
`objdump`是Linux下的反汇编工具,用于将二进制文件转换为汇编代码,便于理解程序底层。它可以反汇编目标文件、可执行文件和库,支持多种参数,如显示符号表(-t)、反汇编代码(-d)、源代码与汇编混合视图(-S)。在实践中,结合-g编译选项和特定段(-j)反汇编,能辅助调试和分析。使用时注意包含调试信息,选择适当参数,并与其他工具(如gdb)配合使用。