# Java éä¹ä¹è§éåæ²è§é * [Java éä¹ä¹è§éåæ²è§é](#java-éä¹ä¹è§éåæ²è§é) * [æ²è§é](#æ²è§é) * [ä¹è§é](#ä¹è§é) * [两ç§éç使ç¨åºæ¯](#两ç§éç使ç¨åºæ¯) * [ä¹è§éçå®ç°æ¹å¼](#ä¹è§éçå®ç°æ¹å¼) * [çæ¬å·æºå¶](#çæ¬å·æºå¶) * [CAS ç®æ³](#cas-ç®æ³) * [ä¹è§éç缺ç¹](#ä¹è§éç缺ç¹) * [ABA é®é¢](#aba-é®é¢) * [循ç¯å¼é大](#循ç¯å¼é大) * [CASä¸synchronizedçä½¿ç¨æ æ¯](#casä¸synchronizedçä½¿ç¨æ æ¯) Java æç §éçå®ç°å为ä¹è§éåæ²è§éï¼ä¹è§éåæ²è§é并䏿¯ä¸ç§çå®åå¨çéï¼èæ¯ä¸ç§è®¾è®¡ææ³ï¼ä¹è§éåæ²è§é对äºçè§£ Java å¤çº¿ç¨åæ°æ®åºæ¥è¯´è³å ³éè¦ï¼é£ä¹æ¬ç¯æç« å°±æ¥è¯¦ç»æ¢è®¨ä¸ä¸è¿ä¸¤ç§éçæ¦å¿µä»¥åå®ç°æ¹å¼ã ## æ²è§é `æ²è§é`æ¯ä¸ç§æ²è§ææ³ï¼å®æ»è®¤ä¸ºæåçæ åµå¯è½ä¼åºç°ï¼å®è®¤ä¸ºæ°æ®å¾å¯è½ä¼è¢«å ¶ä»äººæä¿®æ¹ï¼æä»¥æ²è§éå¨æææ°æ®çæ¶åæ»ä¼æ`èµæº` æè `æ°æ®` éä½ï¼è¿æ ·å ¶ä»çº¿ç¨æ³è¦è¯·æ±è¿ä¸ªèµæºçæ¶åå°±ä¼é»å¡ï¼ç´å°çå°æ²è§éæèµæºéæ¾ä¸ºæ¢ãä¼ ç»çå ³ç³»åæ°æ®åºé边就ç¨å°äºå¾å¤è¿ç§éæºå¶ï¼**æ¯å¦è¡éï¼è¡¨éçï¼è¯»éï¼åéçï¼é½æ¯å¨åæä½ä¹åå ä¸éã**æ²è§éçå®ç°å¾å¾ä¾é æ°æ®åºæ¬èº«çéåè½å®ç°ã Java ä¸ç `Synchronized` å `ReentrantLock` çç¬å é(æä»é)乿¯ä¸ç§æ²è§éææ³çå®ç°ï¼å 为 Synchronzied å ReetrantLock ä¸ç®¡æ¯å¦ææèµæºï¼å®é½ä¼å°è¯å»å éï¼çæèªå·±å¿ç±çå®è´è¢«å«äººæ¿èµ°ã ## ä¹è§é ä¹è§éçææ³ä¸æ²è§éçææ³ç¸åï¼å®æ»è®¤ä¸ºèµæºåæ°æ®ä¸ä¼è¢«å«äººæä¿®æ¹ï¼æä»¥è¯»åä¸ä¼ä¸éï¼ä½æ¯ä¹è§éå¨è¿è¡åå ¥æä½çæ¶åä¼å¤æå½åæ°æ®æ¯å¦è¢«ä¿®æ¹è¿(å ·ä½å¦ä½å¤ææä»¬ä¸é¢å说)ãä¹è§éçå®ç°æ¹æ¡ä¸è¬æ¥è¯´æä¸¤ç§ï¼ `çæ¬å·æºå¶` å `CASå®ç°` ãä¹è§éå¤éç¨äºå¤åº¦çåºç¨ç±»åï¼è¿æ ·å¯ä»¥æé«ååéã å¨Javaä¸`java.util.concurrent.atomic`å ä¸é¢çåååé类就æ¯ä½¿ç¨äºä¹è§éçä¸ç§å®ç°æ¹å¼CASå®ç°çã ## 两ç§éç使ç¨åºæ¯ ä¸é¢ä»ç»äºä¸¤ç§éçåºæ¬æ¦å¿µï¼å¹¶æå°äºä¸¤ç§éçéç¨åºæ¯ï¼ä¸è¬æ¥è¯´ï¼æ²è§éä¸ä» ä¼å¯¹åæä½å éè¿ä¼å¯¹è¯»æä½å éï¼ä¸ä¸ªå ¸åçæ²è§éè°ç¨ï¼ ```mysql select * from student where name="cxuan" for update ``` è¿æ¡ sql è¯å¥ä» Student 表ä¸éå name = "cxuan" çè®°å½å¹¶å¯¹å ¶å éï¼é£ä¹å ¶ä»åæä½åè¿ä¸ªäºå¡æäº¤ä¹åé½ä¸ä¼å¯¹è¿æ¡æ°æ®è¿è¡æä½ï¼èµ·å°äºç¬å åæä»çä½ç¨ã æ²è§éå 为对读åé½å éï¼æä»¥å®çæ§è½æ¯è¾ä½ï¼å¯¹äºç°å¨äºèç½æå¡ç`ä¸é«`(髿§è½ãé«å¯ç¨ãé«å¹¶å)æ¥è¯´ï¼æ²è§éçå®ç°ç¨çè¶æ¥è¶å°äºï¼ä½æ¯ä¸è¬å¤è¯»çæ åµä¸è¿æ¯éè¦ä½¿ç¨æ²è§éçï¼å 为è½ç¶å éçæ§è½æ¯è¾ä½ï¼ä½æ¯ä¹é»æ¢äºåä¹è§é䏿 ·ï¼éå°åä¸ä¸è´çæ åµä¸ä¸ç´éè¯çæ¶é´ã ç¸å¯¹èè¨ï¼ä¹è§éç¨äºè¯»å¤åå°çæ åµï¼å³å¾å°åçå²çªçåºæ¯ï¼è¿æ ·å¯ä»¥çå»éçå¼éï¼å¢å ç³»ç»çååéã ä¹è§éçéç¨åºæ¯æå¾å¤ï¼å ¸åçæ¯å¦è¯´ææ¬ç³»ç»ï¼æåè¦å¯¹ä¸ç¬éé¢åä¿®æ¹ï¼ä¸ºäºä¿è¯æ°æ®çåç¡®æ§å宿æ§ï¼ä½¿ç¨æ²è§ééä½æä¸ªæ°æ®åï¼åéå°å ¶ä»éè¦ä¿®æ¹æ°æ®çæä½ï¼é£ä¹æ¤æä½å°±æ æ³å®æéé¢çä¿®æ¹ï¼å¯¹äº§åæ¥è¯´æ¯ç¾é¾æ§çä¸å»ï¼ä½¿ç¨ä¹è§éççæ¬å·æºå¶è½å¤è§£å³è¿ä¸ªé®é¢ï¼æä»¬ä¸é¢è¯´ã ## ä¹è§éçå®ç°æ¹å¼ ä¹è§éä¸è¬æä¸¤ç§å®ç°æ¹å¼ï¼éç¨`çæ¬å·æºå¶` å `CASï¼Compare-and-Swapï¼å³æ¯è¾å¹¶æ¿æ¢ï¼ç®æ³`å®ç°ã ### çæ¬å·æºå¶ çæ¬å·æºå¶æ¯å¨æ°æ®è¡¨ä¸å ä¸ä¸ä¸ª `version` åæ®µæ¥å®ç°çï¼è¡¨ç¤ºæ°æ®è¢«ä¿®æ¹ç次æ°ï¼å½æ§è¡åæä½å¹¶ä¸åå ¥æååï¼version = version + 1ï¼å½çº¿ç¨Aè¦æ´æ°æ°æ®æ¶ï¼å¨è¯»åæ°æ®çåæ¶ä¹ä¼è¯»å version å¼ï¼å¨æäº¤æ´æ°æ¶ï¼è¥åæè¯»åå°ç version å¼ä¸ºå½åæ°æ®åºä¸çversionå¼ç¸çæ¶ææ´æ°ï¼å¦åéè¯æ´æ°æä½ï¼ç´å°æ´æ°æåã æä»¬ä»¥ä¸é¢çéèç³»ç»ä¸ºä¾ï¼æ¥ç®è¿°ä¸ä¸è¿ä¸ªè¿ç¨ã  - ææ¬ç³»ç»ä¸æä¸ä¸ªæ°æ®è¡¨ï¼è¡¨ä¸æä¸¤ä¸ªå段å嫿¯ `éé¢` å `version`ï¼éé¢ç屿§æ¯è½å¤å®æ¶ååï¼è version è¡¨ç¤ºçæ¯é颿¯æ¬¡åçååççæ¬ï¼ä¸è¬ççç¥æ¯ï¼å½éé¢åçæ¹åæ¶ï¼version éç¨éå¢ççç¥æ¯æ¬¡é½å¨ä¸ä¸ä¸ªçæ¬å·çåºç¡ä¸ + 1ã - å¨äºè§£äºåºæ¬æ åµååºæ¬ä¿¡æ¯ä¹åï¼æä»¬æ¥çä¸ä¸è¿ä¸ªè¿ç¨ï¼å ¬å¸æ¶å°å款åï¼éè¦æè¿ç¬é±æ¾å¨éåºä¸ï¼åå¦éåºä¸åæ100 å é± - ä¸é¢å¼å¯äºå¡ä¸ï¼å½ç·æåæ§è¡å款åå ¥æä½åï¼ä»ä¼å æ¥ç(读)ä¸ä¸éåºä¸è¿æå¤å°é±ï¼æ¤æ¶è¯»å°éåºä¸æ 100 å ï¼å¯ä»¥æ§è¡åæä½ï¼å¹¶ææ°æ®åºä¸ç鱿´æ°ä¸º 120 å ï¼æäº¤äºå¡ï¼éåºä¸çé±ç± 100 -> 120ï¼versionççæ¬å·ç± 0 -> 1ã - å¼å¯äºå¡äºï¼å¥³æåæ¶å°ç»åå·¥åå·¥èµç请æ±åï¼éè¦å æ§è¡è¯»è¯·æ±ï¼æ¥çéåºä¸çé±è¿æå¤å°ï¼æ¤æ¶ççæ¬å·æ¯å¤å°ï¼ç¶åä»éåºä¸ååºåå·¥çå·¥èµè¿è¡åæ¾ï¼æäº¤äºå¡ï¼æååçæ¬ + 1ï¼æ¤æ¶çæ¬ç± 1 -> 2ã **ä¸é¢ä¸¤ç§æ 嵿¯æä¹è§çæ åµï¼ä¸é¢ç两个äºå¡é½æ¯é¡ºåºæ§è¡çï¼ä¹å°±æ¯äºå¡ä¸åäºå¡äºäºä¸å¹²æ°ï¼é£ä¹äºå¡è¦å¹¶è¡æ§è¡ä¼å¦ä½å¢ï¼**  - äºå¡ä¸å¼å¯ï¼ç·æåå æ§è¡è¯»æä½ï¼ååºéé¢åçæ¬å·ï¼æ§è¡åæä½ ```mysql begin update 表 set éé¢ = 120,version = version + 1 where éé¢ = 100 and version = 0 ``` æ¤æ¶é颿¹ä¸º 120ï¼çæ¬å·ä¸º1ï¼äºå¡è¿æ²¡ææäº¤ äºå¡äºå¼å¯ï¼å¥³æåå æ§è¡è¯»æä½ï¼ååºéé¢åçæ¬å·ï¼æ§è¡åæä½ ```mysql begin update 表 set éé¢ = 50,version = version + 1 where éé¢ = 100 and version = 0 ``` æ¤æ¶é颿¹ä¸º 50ï¼çæ¬å·å为 1ï¼äºå¡æªæäº¤ ç°å¨æäº¤äºå¡ä¸ï¼é颿¹ä¸º 120ï¼çæ¬å为1ï¼æäº¤äºå¡ãçæ³æ åµä¸åºè¯¥å为 éé¢ = 50ï¼çæ¬å· = 2ï¼ä½æ¯å®é ä¸äºå¡äº çæ´æ°æ¯å»ºç«å¨éé¢ä¸º 100 å çæ¬å·ä¸º 0 çåºç¡ä¸çï¼æä»¥äºå¡äºä¸ä¼æäº¤æåï¼åºè¯¥éæ°è¯»åéé¢åçæ¬å·ï¼å次è¿è¡åæä½ã è¿æ ·ï¼å°±é¿å äºå¥³æå ç¨åºäº version=0 çæ§æ°æ®ä¿®æ¹çç»æè¦çç·æä½åæä½ç»æçå¯è½ã ### CAS ç®æ³ å æ¥çä¸éç»å ¸çå¹¶åæ§è¡ 1000次éå¢åéååçé®é¢ï¼ ```java public class Counter { int count = 0; public int getCount() { return count; } public void setCount(int count) { this.count = count; } public void add(){ count += 1; } public void dec(){ count -= 1; } } ``` ```java public class Consumer extends Thread{ Counter counter; public Consumer(Counter counter){ this.counter = counter; } @Override public void run() { for(int j = 0;j < Test.LOOP;j++){ counter.dec(); } } } public class Producer extends Thread{ Counter counter; public Producer(Counter counter){ this.counter = counter; } @Override public void run() { for(int i = 0;i < Test.LOOP;++i){ counter.add(); } } } public class Test { final static int LOOP = 1000; public static void main(String[] args) throws InterruptedException { Counter counter = new Counter(); Producer producer = new Producer(counter); Consumer consumer = new Consumer(counter); producer.start(); consumer.start(); producer.join(); consumer.join(); System.out.println(counter.getCount()); } } ``` 夿¬¡æµè¯çç»æé½ä¸ä¸º 0ï¼ä¹å°±æ¯è¯´åºç°äºå¹¶ååæ°æ®ä¸ä¸è´çé®é¢ï¼åå æ¯ count -= 1 å count += 1 齿¯éååæ§æä½ï¼å®ä»¬çæ§è¡æ¥éª¤åä¸ºä¸æ¥ï¼ - ä»å åä¸è¯»å count çå¼ï¼æå®æ¾å ¥å¯åå¨ä¸ - æ§è¡ + 1 æè - 1 æä½ - æ§è¡å®æçç»æåå¤å¶å°å åä¸ å¦æè¦æè¯å®ä»¬çååæ§ï¼å¿ é¡»è¿è¡å éï¼ä½¿ç¨ `Synchronzied` æè `ReentrantLock`ï¼æä»¬åé¢ä»ç»å®ä»¬æ¯æ²è§éçå®ç°ï¼æä»¬ç°å¨è®¨è®ºçæ¯ä¹è§éï¼é£ä¹ç¨åªç§æ¹å¼ä¿è¯å®ä»¬çååæ§å¢ï¼è¯·ç»§ç»å¾ä¸ç CAS å³ `compare and swapï¼æ¯è¾ä¸äº¤æ¢ï¼`ï¼æ¯ä¸ç§æåçæ éç®æ³ãå³ä¸ä½¿ç¨éçæ åµä¸å®ç°å¤çº¿ç¨ä¹é´çåé忥ï¼ä¹å°±æ¯å¨æ²¡æçº¿ç¨è¢«é»å¡çæ åµä¸å®ç°åéçåæ¥ï¼æä»¥ä¹å«éé»å¡åæ¥ï¼Non-blocking Synchronization CAS 䏿¶åä¸ä¸ªè¦ç´ ï¼ - éè¦è¯»åçå åå¼ V - è¿è¡æ¯è¾çå¼ A - æåå ¥çæ°å¼ B å½ä¸ä» å½é¢æå¼Aåå åå¼Vç¸åæ¶ï¼å°å åå¼Vä¿®æ¹ä¸ºBï¼å¦åä»ä¹é½ä¸åã JAVA对CASçæ¯æï¼å¨JDK1.5 䏿°æ·»å java.util.concurrent (J.U.C) å°±æ¯å»ºç«å¨ CAS ä¹ä¸çãå¯¹äº synchronized è¿ç§é»å¡ç®æ³ï¼CASæ¯éé»å¡ç®æ³çä¸ç§å®ç°ãæä»¥J.U.C卿§è½ä¸æäºå¾å¤§çæåã æä»¬ä»¥ java.util.concurrent ä¸ç` AtomicInteger` 为ä¾ï¼çä¸ä¸å¨ä¸ç¨éçæ åµä¸æ¯å¦ä½ä¿è¯çº¿ç¨å®å ¨ç ```java public class AtomicCounter { private AtomicInteger integer = new AtomicInteger(); public AtomicInteger getInteger() { return integer; } public void setInteger(AtomicInteger integer) { this.integer = integer; } public void increment(){ integer.incrementAndGet(); } public void decrement(){ integer.decrementAndGet(); } } public class AtomicProducer extends Thread{ private AtomicCounter atomicCounter; public AtomicProducer(AtomicCounter atomicCounter){ this.atomicCounter = atomicCounter; } @Override public void run() { for(int j = 0; j < AtomicTest.LOOP; j++) { System.out.println("producer : " + atomicCounter.getInteger()); atomicCounter.increment(); } } } public class AtomicConsumer extends Thread{ private AtomicCounter atomicCounter; public AtomicConsumer(AtomicCounter atomicCounter){ this.atomicCounter = atomicCounter; } @Override public void run() { for(int j = 0; j < AtomicTest.LOOP; j++) { System.out.println("consumer : " + atomicCounter.getInteger()); atomicCounter.decrement(); } } } public class AtomicTest { final static int LOOP = 10000; public static void main(String[] args) throws InterruptedException { AtomicCounter counter = new AtomicCounter(); AtomicProducer producer = new AtomicProducer(counter); AtomicConsumer consumer = new AtomicConsumer(counter); producer.start(); consumer.start(); producer.join(); consumer.join(); System.out.println(counter.getInteger()); } } ``` ç»æµè¯å¯å¾ï¼ä¸ç®¡å¾ªç¯å¤å°æ¬¡æåçç»æé½æ¯0ï¼ä¹å°±æ¯å¤çº¿ç¨å¹¶è¡çæ åµä¸ï¼ä½¿ç¨ AtomicInteger å¯ä»¥ä¿è¯çº¿ç¨å®å ¨æ§ã incrementAndGet å decrementAndGet 齿¯ååæ§æä½ãæ¬ç¯æç« æä¸æ¢è®¨å®ä»¬çå®ç°æ¹å¼ã ## ä¹è§éçç¼ºç¹ ä»»ä½äºæ 齿¯æå©ä¹æå¼ï¼è½¯ä»¶è¡ä¸æ²¡æå®ç¾çè§£å³æ¹æ¡åªææä¼çè§£å³æ¹æ¡ï¼æä»¥ä¹è§é乿å®çå¼±ç¹å缺é·ï¼ ### ABA é®é¢ ABA é®é¢è¯´çæ¯ï¼å¦æä¸ä¸ªåéç¬¬ä¸æ¬¡è¯»åç弿¯ Aï¼åå¤å¥½éè¦å¯¹ A è¿è¡åæä½çæ¶åï¼åç°å¼è¿æ¯ Aï¼é£ä¹è¿ç§æ åµä¸ï¼è½è®¤ä¸º A ç弿²¡æè¢«æ¹åè¿åï¼å¯ä»¥æ¯ç± A -> B -> A çè¿ç§æ åµï¼ä½æ¯ AtomicInteger å´ä¸ä¼è¿ä¹è®¤ä¸ºï¼å®åªç¸ä¿¡å®çå°çï¼å®çå°çæ¯ä»ä¹å°±æ¯ä»ä¹ã JDK 1.5 以åç `AtomicStampedReference `类就æä¾äºæ¤ç§è½åï¼å ¶ä¸ç `compareAndSet æ¹æ³`å°±æ¯é¦å æ£æ¥å½åå¼ç¨æ¯å¦çäºé¢æå¼ç¨ï¼å¹¶ä¸å½åæ å¿æ¯å¦çäºé¢ææ å¿ï¼å¦æå ¨é¨ç¸çï¼å以ååæ¹å¼å°è¯¥å¼ç¨å该æ å¿çå¼è®¾ç½®ä¸ºç»å®çæ´æ°å¼ã ä¹å¯ä»¥éç¨CASçä¸ä¸ªåç§DCASæ¥è§£å³è¿ä¸ªé®é¢ã DCASï¼æ¯å¯¹äºæ¯ä¸ä¸ªVå¢å ä¸ä¸ªå¼ç¨çè¡¨ç¤ºä¿®æ¹æ¬¡æ°çæ 记符ãå¯¹äºæ¯ä¸ªVï¼å¦æå¼ç¨ä¿®æ¹äºä¸æ¬¡ï¼è¿ä¸ªè®¡æ°å¨å°±å 1ãç¶ååè¿ä¸ªåééè¦updateçæ¶åï¼å°±åæ¶æ£æ¥åéçå¼å计æ°å¨çå¼ã ### 循ç¯å¼é大 æä»¬ç¥éä¹è§éå¨è¿è¡åæä½çæ¶åä¼å¤ææ¯å¦è½å¤åå ¥æåï¼å¦æåå ¥ä¸æåå°è§¦åçå¾ -> éè¯æºå¶ï¼è¿ç§æ 嵿¯ä¸ä¸ªèªæéï¼ç®åæ¥è¯´å°±æ¯éç¨äºçæå è·åä¸å°ï¼è¿è¡çå¾ éè¯çéï¼å®ä¸éç¨äºé¿æè·åä¸å°éçæ åµï¼å¦å¤ï¼èªæå¾ªç¯å¯¹äºæ§è½å¼éæ¯è¾å¤§ã ## CASä¸synchronizedçä½¿ç¨æ æ¯ ç®åçæ¥è¯´ CAS éç¨äºåæ¯è¾å°çæ åµä¸ï¼å¤è¯»åºæ¯ï¼å²çªä¸è¬è¾å°ï¼ï¼synchronized éç¨äºåæ¯è¾å¤çæ åµä¸ï¼å¤ååºæ¯ï¼å²çªä¸è¬è¾å¤ï¼ - 对äºèµæºç«äºè¾å°ï¼çº¿ç¨å²çªè¾è½»ï¼çæ åµï¼ä½¿ç¨ synchronized 忥éè¿è¡çº¿ç¨é»å¡åå¤é忢以åç¨æ·æå æ ¸æé´ç忢æä½é¢å¤æµªè´¹æ¶è cpu èµæºï¼è CAS åºäºç¡¬ä»¶å®ç°ï¼ä¸éè¦è¿å ¥å æ ¸ï¼ä¸éè¦åæ¢çº¿ç¨ï¼æä½èªæå çè¾å°ï¼å æ¤å¯ä»¥è·å¾æ´é«çæ§è½ã - 对äºèµæºç«äºä¸¥éï¼çº¿ç¨å²çªä¸¥éï¼çæ åµï¼CAS èªæçæ¦ç伿¯è¾å¤§ï¼ä»è浪费æ´å¤ç CPU èµæºï¼æçä½äº synchronizedã > è¡¥å ï¼ Javaå¹¶åç¼ç¨è¿ä¸ªé¢åä¸ synchronized å ³é®åä¸ç´é½æ¯å è级çè§è²ï¼å¾ä¹ ä¹åå¾å¤äººé½ä¼ç§°å®ä¸º âéé级éâ ã使¯ï¼å¨JavaSE 1.6ä¹åè¿è¡äºä¸»è¦å æ¬ä¸ºäºåå°è·å¾éåéæ¾é带æ¥çæ§è½æ¶èèå¼å ¥ç ååé å è½»é级é 以åå ¶å®åç§ä¼åä¹ååå¾å¨æäºæ åµä¸å¹¶ä¸æ¯é£ä¹éäºãsynchronized çåºå±å®ç°ä¸»è¦ä¾é Lock-Free çéåï¼åºæ¬æè·¯æ¯ èªæåé»å¡ï¼ç«äºåæ¢åç»§ç»ç«äºéï¼ç¨å¾®çºç²äºå ¬å¹³æ§ï¼ä½è·å¾äºé«ååéãå¨çº¿ç¨å²çªè¾å°çæ åµä¸ï¼å¯ä»¥è·å¾å CAS ç±»ä¼¼çæ§è½ï¼è线ç¨å²çªä¸¥éçæ åµä¸ï¼æ§è½è¿é«äºCASã  