如何优化东莞家政服务网站的WordPress以提升用户体验?
摘要:家政 东莞网站建设,wordpress解析优化,百度关键词价格排行榜,做黄漫画网站互斥锁与自旋锁 最底层的两种就是 [互斥锁和自旋锁],有很多高级的锁都是基于它们实现的。可以认为它们是各种锁的地基&am
家政 东莞网站建设,wordpress解析优化,百度关键词价格排行榜,做黄漫画网站互斥锁与自旋锁
最底层的两种就是 [互斥锁和自旋锁]#xff0c;有很多高级的锁都是基于它们实现的。可以认为它们是各种锁的地基#xff0c;所以我们必须清楚它们之间的区别和应用。
加锁的目的就是保证共享资源在任意时间内#xff0c;只有一个线程访问#xff0c;这样就…互斥锁与自旋锁
最底层的两种就是 [互斥锁和自旋锁]有很多高级的锁都是基于它们实现的。可以认为它们是各种锁的地基所以我们必须清楚它们之间的区别和应用。
加锁的目的就是保证共享资源在任意时间内只有一个线程访问这样就可以避免多线程导致共享数据错乱的问题。
当已经有一个线程加锁后其他线程加锁就会失败互斥锁盒自旋锁对于加锁失败后的处理方式是不一样的
互斥锁加锁失败后线程会释放CPU给其他线程自旋锁加锁失败后线程会忙等待直到它拿到锁
互斥锁是一种 [独占锁]比如当线程 A 加锁成功后此时互斥锁已经被线程 A 独占了只要线程 A 没有释放手中的锁线程 B 加锁就会失败于是就会释放 CPU 让给其他线程既然线程 B 释放掉了 CPU 自然线程 B 加锁的代码就会被阻塞。
对于互斥锁加锁失败而阻塞的现象是由操作系统内核实现的。当加锁失败时内核会将线程置位睡眠状态等到锁被释放后内核会在合适的时机唤醒线程当这个线程成功获取到锁后于是就可以继续执行。如下图 所以互斥锁加锁失败时会从用户态陷入到内核态让内核帮我们切换线程虽然简化了使用锁的难度但是存在一定的性能开销。
那这个开销成本是什么呢会有两次线程上下文切换的成本
当线程加锁失败时内核会把线程的状态从 [运行] 状态设置为 [睡眠] 状态然后把 CPU切换给其他线程运行接着当锁被释放时之前 [睡眠] 状态的线程会变为 [就绪] 状态然后内核会在合适的时间吧CPU切换给该线程运行。 线程的上下文切换是什么 当两个线程是属于同一个进程因为虚拟内存时共享的所以在切换时虚拟内存这些资源保持不动只需要切换线程的私有数据、寄存器等不共享的数据。 上下文切换的耗时有人统计过大概在几十纳秒到几微秒之间如果锁住的代码执行时间比较短那可能上下文切换的时间都比锁住的代码执行时间还要长。
所以如果能确定被锁住的代码执行时间很短就不应该用互斥锁而应该选用自旋锁否则使用互斥锁。
自旋锁是通过CPU提供的 CAS 函数在 用户态 完成加锁和解锁的操作不会产生线程上下文切换所以相比互斥锁来说会快一些开销也小一些。
一般加锁的过程包含两个步骤
第一步查看锁的状态如果锁的空闲的则执行第二步第二步将锁设置为当前线程持有 CAS 函数就把这两个步骤合并成一条硬件级执行形成原子指令这样就保证了这两个步骤是不可分割的要么一次性执行完两个步骤要么两个步骤都不执行。
使用自旋锁的时候当发生多线程竞争锁的情况加锁失败的线程会 [忙等待] 直到它拿到锁。这里的忙等待可以用 while 循环等待实现不过最好是使用 CPU 提供的 PAUSE 指令来实现 忙等待因为可以减少循环等待的耗电量。
自旋锁是比较简单的一种锁一直自旋利用 CPU 周期直到锁可用。需要注意在单核 CPU上需要抢占式的调度器即不断通过时钟中断一个线程运行其他线程。否则自旋锁在单CPU上无法使用因为一个自旋的线程永远不会放弃CPU。
自旋锁开销少在多核系统下一般不会主动产生线程切换适合异步、协程等在用户态切换请求的编程方式但如果被锁住的代码执行时间过长自旋的线程会长时间占用CPU资源所以自旋的时间和被锁住的代码执行的时间是成 正比 的关系。
自旋锁与互斥锁使用层面比较相似但实现层面上完全不同当加锁失败时互斥锁用 [线程切换] 来应对自旋锁则用 [忙等待] 来应对。
它俩是锁的最基本处理方式更高级的锁都会选择其中一个来实现比如读写锁既可以选择互斥锁实现也可以基于自旋锁实现。 读写锁
读写锁从字面意思就是由 [读锁] 和 [写锁] 两部分组成如果只读取共享资源用 [读锁] 加锁如果需要修改共享资源则用 [写锁] 加锁。
所以,读写锁适用于能明确区分读操作和写操作的场景。
读写锁的工作原理是
当 [写锁] 没有被线程持有时多个线程能够并发地持有读锁这大大提高了共享资源的访问效率因为 [读锁] 是用于读取共享资源的场景所以多个线程同时持有读锁也不会破坏共享资源的数据。但是一旦 [写锁] 被线程持有后读线程的获取读锁的操作会被阻塞而且其他写线程的获取写锁的操作也会被阻塞。
所以说写锁是独占锁因为任何时刻只能有一个线程有写锁类似互斥锁和自旋锁而读锁是共享锁因为读锁可以被多个线程同时持有。
读写锁在读多写少的场景能发挥出优势。
另外根据实现的不同读写锁可以分为 [读优先锁] 和 [写优先锁] 。
