1.Linux 内核 rcu(顺序) 锁实现原理与源码解析
2.HashMapåHashtableçåºå«
3.synchronize底层原理
4.Lockçawait/singal å Objectçwait/notify çåºå«
Linux 内核 rcu(顺序) 锁实现原理与源码解析
结论是,Linux 内核中的 RCU(Read-Copy-Update)锁提供了一种无需阻塞的锁机制,旨在提高并发性能。传统的锁如自旋锁和互斥锁存在阻塞问题,而RCU锁通过读写分离、延迟删除策略来实现无锁或低阻塞的flac编码源码操作。
RCU锁的核心原理是利用读写分离的策略。当有读任务 M 阅读链表时,写任务 N 可以在读任务完成后再进行修改,通过rcu_assign_pointer 修改指针,保留旧节点直到读任务结束。写任务通过synchronize_kernel等待所有读任务完成,而读任务则通过rcu_read_lock获取读锁,rcu_read_unlock释放,rcu_dereference访问数据。
这种机制类似于垃圾回收机制,写者在操作后保留旧引用,xscript 源码直到所有读任务结束才删除。rcu_read_lock会禁止抢占,形成一个宽限期,确保读任务在读锁保护下完成,从而避免数据不一致。
总的来说,RCU锁通过巧妙的策略,实现了低阻塞的天鹅源码并发控制,提高系统性能,而源码中的关键操作包括rcu_assign_pointer进行指针更新,synchronize_kernel等待读任务完成,以及读任务通过rcu_read_lock等函数进行锁的管理和数据访问。
HashMapåHashtableçåºå«
HashMapåHashtableçæ¯è¾æ¯Javaé¢è¯ä¸ç常è§é®é¢ï¼ç¨æ¥èéªç¨åºåæ¯å¦è½å¤æ£ç¡®ä½¿ç¨éå类以åæ¯å¦å¯ä»¥éæºåºå使ç¨å¤ç§æ路解å³é®é¢ãHashMapçå·¥ä½åçãArrayListä¸Vectorçæ¯è¾ä»¥åè¿ä¸ªé®é¢æ¯æå ³Java éåæ¡æ¶çæç»å ¸çé®é¢ãHashtableæ¯ä¸ªè¿æ¶çéåç±»ï¼åå¨äºJava APIä¸å¾ä¹ äºãå¨Java 4ä¸è¢«éåäºï¼å®ç°äºMapæ¥å£ï¼æ以èªæ¤ä»¥åä¹æäºJavaéåæ¡æ¶ä¸çä¸é¨åãHashtableåHashMapå¨Javaé¢è¯ä¸ç¸å½å®¹æ被é®å°ï¼çè³æ为äºéåæ¡æ¶é¢è¯é¢ä¸æ常被èçé®é¢ï¼æ以å¨åå ä»»ä½Javaé¢è¯ä¹åï¼é½ä¸è¦å¿äºåå¤è¿ä¸é¢ã
è¿ç¯æç« ä¸ï¼æ们ä¸ä» å°ä¼çå°HashMapåHashtableçåºå«ï¼è¿å°çå°å®ä»¬ä¹é´çç¸ä¼¼ä¹å¤ã
HashMapåHashtableé½å®ç°äºMapæ¥å£ï¼ä½å³å®ç¨åªä¸ä¸ªä¹åå è¦å¼æ¸ æ¥å®ä»¬ä¹é´çåå«ã主è¦çåºå«æï¼çº¿ç¨å®å ¨æ§ï¼åæ¥(synchronization)ï¼ä»¥åé度ã
ç±äºHashtableæ¯çº¿ç¨å®å ¨çä¹æ¯synchronizedï¼æ以å¨å线ç¨ç¯å¢ä¸å®æ¯HashMapè¦æ ¢ãå¦æä½ ä¸éè¦åæ¥ï¼åªéè¦åä¸çº¿ç¨ï¼é£ä¹ä½¿ç¨HashMapæ§è½è¦å¥½è¿Hashtableã
HashMapä¸è½ä¿è¯éçæ¶é´çæ¨ç§»Mapä¸çå ç´ æ¬¡åºæ¯ä¸åçã
fail-fastæºå¶å¨éåä¸ä¸ªéåæ¶ï¼å½éåç»æ被修æ¹ï¼ä¼æåºConcurrent Modification Exceptionã
fail-fastä¼å¨ä»¥ä¸ä¸¤ç§æ åµä¸æåºConcurrentModificationException
éå被å建åï¼å¨éåå®çè¿ç¨ä¸ä¿®æ¹äºç»æã
注æ remove()æ¹æ³ä¼è®©expectModcountåmodcount ç¸çï¼æ以æ¯ä¸ä¼æåºè¿ä¸ªå¼å¸¸ã
å½ä¸ä¸ªçº¿ç¨å¨éåè¿ä¸ªéåï¼èå¦ä¸ä¸ªçº¿ç¨å¯¹è¿ä¸ªéåçç»æè¿è¡äºä¿®æ¹ã
è¿ä»£å¨å¨éåè¿ç¨ä¸æ¯ç´æ¥è®¿é®å é¨æ°æ®çï¼å æ¤å é¨çæ°æ®å¨éåçè¿ç¨ä¸æ æ³è¢«ä¿®æ¹ã为äºä¿è¯ä¸è¢«ä¿®æ¹ï¼è¿ä»£å¨å é¨ç»´æ¤äºä¸ä¸ªæ è®° âmodeâ ï¼å½éåç»ææ¹åï¼æ·»å å é¤æè ä¿®æ¹ï¼ï¼æ è®°"mode"ä¼è¢«ä¿®æ¹ï¼èè¿ä»£å¨æ¯æ¬¡çhasNext()ånext()æ¹æ³é½ä¼æ£æ¥è¯¥"mode"æ¯å¦è¢«æ¹åï¼å½æ£æµå°è¢«ä¿®æ¹æ¶ï¼æåºConcurrent Modification Exceptionã
ä¸é¢ççArrayListè¿ä»£å¨é¨åçæºç ã
å¯ä»¥çå°å®çæ è®°âmodeâ为 expectedModeCountã
fail-safeä»»ä½å¯¹éåç»æçä¿®æ¹é½ä¼å¨ä¸ä¸ªå¤å¶çéåä¸è¿è¡ä¿®æ¹ï¼å æ¤ä¸ä¼æåºConcurrentModificationExceptionã
fail-safeæºå¶æ两个é®é¢
HashMapå¯ä»¥éè¿ä¸é¢çè¯å¥è¿è¡åæ¥ï¼
Map m = Collections.synchronizeMap(hashMap);
HashtableåHashMapæå 个主è¦çä¸åï¼çº¿ç¨å®å ¨ä»¥åé度ãä» å¨ä½ éè¦å®å ¨ç线ç¨å®å ¨çæ¶å使ç¨Hashtableï¼èå¦æä½ ä½¿ç¨Java 5æ以ä¸çè¯ï¼è¯·ä½¿ç¨ConcurrentHashMapå§ã
synchronize底层原理
synchronize底层原理是什么?我们先通过反编译下面的代码来看看Synchronized是如何实现对代码块进行同步的:
1 package com.paddx.test.concurrent;
2
3 public class SynchronizedDemo {
4 public void method() {
5 synchronized (this) {
6 System.out.println(Method 1 start);
7 }
8 }
9 }
反编译结果:
关于这两条指令的作用,我们直接参考JVM规范中描述:
monitorenter :
Each object is associated with a monitor. A monitor is locked if and only if it has an owner. The thread that executes monitorenter attempts to gain ownership of the monitor associated with objectref, as follows:
If the entry count of the monitor associated with objectref is zero, the thread enters the monitor and sets its entry count to one. The thread is then the owner of the monitor.
If the thread already owns the monitor associated with objectref, it reenters the monitor, incrementing its entry count.
If another thread already owns the monitor associated with objectref, the thread blocks until the monitors entry count is zero, then tries again to gain ownership.
这段话的大概意思为:
每个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的ipmana源码所有权,过程:
1、如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。
2、如果线程已经占有该monitor,只是10101101源码重新进入,则进入monitor的进入数加1.
3.如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。
monitorexit:
The thread that executes monitorexit must be the owner of the monitor associated with the instance referenced by objectref.
The thread decrements the entry count of the monitor associated with objectref. If as a result the value of the entry count is zero, the thread exits the monitor and is no longer its owner. Other threads that are blocking to enter the monitor are allowed to attempt to do so.
这段话的大概意思为:
执行monitorexit的线程必须是objectref所对应的monitor的所有者。
指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor 的所有权。
通过这两段描述,我们应该能很清楚的看出Synchronized的实现原理,Synchronized的语义底层是通过一个monitor的对象来完成,其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。
我们再来看一下同步方法的反编译结果:
源代码:
1 package com.paddx.test.concurrent;
2
3 public class SynchronizedMethod {
4 public synchronized void method() {
5 System.out.println(Hello World!);
6 }
7 }
反编译结果:
从反编译的结果来看,方法的同步并没有通过指令monitorenter和monitorexit来完成(理论上其实也可以通过这两条指令来实现),不过相对于普通方法,其常量池中多了ACC_SYNCHRONIZED标示符。JVM就是根据该标示符来实现方法的同步的:当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他任何线程都无法再获得同一个monitor对象。 其实本质上没有区别,只是方法的同步是一种隐式的方式来实现,无需通过字节码来完成。
Lockçawait/singal å Objectçwait/notify çåºå«
Lockçawait/singal å Objectçwait/notify çåºå«
å¨ä½¿ç¨Lockä¹åï¼æ们é½ä½¿ç¨Object çwaitånotifyå®ç°åæ¥çã举ä¾æ¥è¯´ï¼ä¸ä¸ªproduceråconsumerï¼consumeråç°æ²¡æä¸è¥¿äºï¼çå¾ ï¼produerçæä¸è¥¿äºï¼å¤éã
线ç¨consumer 线ç¨producer
synchronize(obj){
obj.wait();//没ä¸è¥¿äºï¼çå¾
} synchronize(obj){
obj.notify();//æä¸è¥¿äºï¼å¤é
}
æäºlockåï¼ä¸éåäºï¼ç°å¨æ¯ï¼
lock.lock();
condition.await();
lock.unlock(); lock.lock();
condition.signal();
lock.unlock();
为äºçªåºåºå«ï¼çç¥äºè¥å¹²ç»èãåºå«æä¸ç¹ï¼
1. lockä¸åç¨synchronizeæåæ¥ä»£ç å è£ èµ·æ¥ï¼
2. é»å¡éè¦å¦å¤ä¸ä¸ªå¯¹è±¡conditionï¼
3. åæ¥åå¤éç对象æ¯conditionèä¸æ¯lockï¼å¯¹åºçæ¹æ³æ¯awaitåsignalï¼èä¸æ¯waitånotifyã
为
ä»ä¹éè¦ä½¿ç¨conditionå¢ï¼ç®åä¸å¥è¯ï¼lockæ´çµæ´»ã以åçæ¹å¼åªè½æä¸ä¸ªçå¾ éåï¼å¨å®é åºç¨æ¶å¯è½éè¦å¤ä¸ªï¼æ¯å¦è¯»ååã为äºè¿ä¸ªçµæ´»
æ§ï¼lockå°åæ¥äºæ¥æ§å¶åçå¾ éåå离å¼æ¥ï¼äºæ¥ä¿è¯å¨æ个æ¶å»åªæä¸ä¸ªçº¿ç¨è®¿é®ä¸´çåºï¼lockèªå·±å®æï¼ï¼çå¾ éåè´è´£ä¿å被é»å¡ç线ç¨
ï¼conditionå®æï¼ã
éè¿æ¥çReentrantLockçæºä»£ç åç°ï¼conditionå ¶å®æ¯çå¾ éåçä¸ä¸ªç®¡çè ï¼conditionç¡®ä¿é»å¡ç对象æ顺åºè¢«å¤éã
å¨Lockçå®ç°ä¸ï¼LockSupport被ç¨æ¥å®ç°çº¿ç¨ç¶æçæ¹åï¼åç»å°æ´è¿ä¸æ¥ç 究LockSupportçå®ç°æºå¶ã