µ±Ç°Î»ÖãºÖ÷Ò³ > ²é¿´ÄÚÈÝ

Java¸ß²¢·¢Ñ§Ï°±Ê¼Ç£¨ËÄ£©£ºvolatile¹Ø¼ü×Ö

·¢²¼Ê±¼ä£º2021-05-16 00:00| ÓРλÅóÓѲ鿴

¼ò½é£º1 À´Ô´ À´Ô´£º¡¶Java¸ß²¢·¢±à³ÌÏê½â ¶àÏß³ÌÓë¼Ü¹¹Éè¼Æ¡·£¬ÍôÎľýÖø Õ½ڣºµÚÊ®¶þ¡¢Ê®ÈýÕ ±¾ÎÄÊÇÁ½ÕµıʼÇÕûÀí¡£ 2 CPU »º´æ 2.1 »º´æÄ£ÐÍ ¼ÆËã»úÖеÄËùÓÐÔËËã²Ù×÷¶¼ÊÇÓÉ CPU Íê³ÉµÄ£¬ CPU Ö¸ÁîÖ´Ðйý³ÌÐèÒªÉæ¼°Êý¾Ý¶ÁÈ¡ºÍдÈë²Ù×÷£¬µ«ÊÇ CPU Ö»ÄÜ·ÃÎÊ´¦ÓÚ¡­¡­

1 À´Ô´

  • À´Ô´£º¡¶Java¸ß²¢·¢±à³ÌÏê½â ¶àÏß³ÌÓë¼Ü¹¹Éè¼Æ¡·£¬ÍôÎľýÖø
  • Õ½ڣºµÚÊ®¶þ¡¢Ê®ÈýÕÂ

±¾ÎÄÊÇÁ½ÕµıʼÇÕûÀí¡£

2 CPU»º´æ

2.1 »º´æÄ£ÐÍ

¼ÆËã»úÖеÄËùÓÐÔËËã²Ù×÷¶¼ÊÇÓÉCPUÍê³ÉµÄ£¬CPUÖ¸ÁîÖ´Ðйý³ÌÐèÒªÉæ¼°Êý¾Ý¶ÁÈ¡ºÍдÈë²Ù×÷£¬µ«ÊÇCPUÖ»ÄÜ·ÃÎÊ´¦ÓÚÄÚ´æÖеÄÊý¾Ý£¬¶øÄÚ´æµÄËٶȺÍCPUµÄËÙ¶ÈÊÇÔ¶Ô¶²»¶ÔµÈµÄ£¬Òò´Ë¾Í³öÏÖÁË»º´æÄ£ÐÍ£¬Ò²¾ÍÊÇÔÚCPUºÍÄÚ´æÖ®¼ä¼ÓÈëÁË»º´æ²ã¡£Ò»°ãÏÖ´úµÄCPU»º´æ²ã·ÖΪÈý¼¶£¬·Ö±ð½ÐL1»º´æ¡¢L2»º´æºÍL3»º´æ£¬¼òÂÔͼÈçÏ£º

ÔÚÕâÀï²åÈëͼƬÃèÊö

  • L1»º´æ£ºÈý¼¶»º´æÖзÃÎÊËÙ¶È×î¿ì£¬µ«ÊÇÈÝÁ¿×îС£¬ÁíÍâL1»º´æ»¹±»»®·Ö³ÉÁËÊý¾Ý»º´æ£¨L1d£¬dataÊ××Öĸ£©ºÍÖ¸Á´æ£¨L1i£¬instructionÊ××Öĸ£©
  • L2»º´æ£ºËٶȱÈL1Âý£¬µ«ÊÇÈÝÁ¿±ÈL1´ó£¬ÔÚÏÖ´úµÄ¶àºËCPUÖУ¬L2Ò»°ã±»µ¥¸öºË¶ÀÕ¼
  • L3»º´æ£ºÈý¼¶»º´æÖÐËÙ¶È×îÂý£¬µ«ÊÇÈÝÁ¿×î´ó£¬ÏÖ´úCPUÖÐÒ²ÓÐL3ÊǶàºË¹²ÏíµÄÉè¼Æ£¬±ÈÈçzen3¼Ü¹¹µÄÉè¼Æ

ÔÚÕâÀï²åÈëͼƬÃèÊö

»º´æµÄ³öÏÖ£¬ÊÇΪÁ˽â¾öCPUÖ±½Ó·ÃÎÊÄÚ´æЧÂʵÍϵÄÎÊÌ⣬CPU½øÐÐÔËËãµÄʱºò£¬½«ÐèÒªµÄÊý¾Ý´ÓÖ÷´æ¸´ÖÆÒ»·Ýµ½»º´æÖУ¬ÒòΪ»º´æµÄ·ÃÎÊËٶȿìÓÚÄڴ棬ÔÚ¼ÆËãµÄʱºòÖ»ÐèÒª¶ÁÈ¡»º´æ²¢½«½á¹û¸üе½»º´æ£¬ÔËËã½áÊøÔÙ½«½á¹ûˢе½Ö÷´æ£¬ÕâÑù¾Í´ó´óÌá¸ßÁ˼ÆËãЧÂÊ£¬ÕûÌå½»»¥Í¼¼òÂÔÈçÏ£º

ÔÚÕâÀï²åÈëͼƬÃèÊö

2.2 »º´æÒ»ÖÂÐÔÎÊÌâ

ËäÈ»»º´æµÄ³öÏÖ£¬´ó´óÌá¸ßÁËÍÌÍÂÄÜÁ¦£¬µ«ÊÇ£¬Ò²ÒýÈëÁËÒ»¸öеÄÎÊÌ⣬¾ÍÊÇ»º´æ²»Ò»Ö¡£±ÈÈ磬×î¼òµ¥µÄÒ»¸öi++²Ù×÷£¬ÐèÒª½«ÄÚ´æÊý¾Ý¸´ÖÆÒ»·Ýµ½»º´æÖУ¬CPU¶ÁÈ¡»º´æÖµ²¢½øÐиüУ¬ÏÈдÈ뻺´æ£¬ÔËËã½áÊøºóÔÙ½«»º´æÖÐеÄˢе½Äڴ棬¾ßÌå¹ý³ÌÈçÏ£º

  • ¶ÁÈ¡ÄÚ´æÖеÄiµ½»º´æÖÐ
  • CPU¶ÁÈ¡»º´æiÖеÄÖµ
  • ¶Ôi½øÐмÓ1²Ù×÷
  • ½«½á¹ûд»Ø»º´æ
  • ÔÙ½«Êý¾Ýˢе½Ö÷´æ

ÕâÑùµÄi++²Ù×÷ÔÚµ¥Ï̲߳»»á³öÏÖÎÊÌ⣬µ«ÔÚ¶àÏß³ÌÖУ¬ÒòΪÿ¸öÏ̶߳¼ÓÐ×Ô¼ºµÄ¹¤×÷Äڴ棨Ҳ½Ð±¾µØÄڴ棬ÊÇÏß³Ì×Ô¼ºµÄ»º´æ£©£¬±äÁ¿iÔÚ¶à¸öÏ̵߳ı¾µØÄÚ´æÖж¼´æÔÚÒ»¸ö¸±±¾£¬Èç¹ûÓÐÁ½¸öÏß³ÌÖ´ÐÐi++²Ù×÷£º

  • ¼ÙÉèÁ½¸öÏß³ÌΪA¡¢B£¬Í¬Ê±¼ÙÉèi³õʼֵΪ0
  • Ïß³ÌA´ÓÄÚ´æÖжÁÈ¡iµÄÖµ·ÅÈ뻺´æÖУ¬´ËʱiµÄֵΪ0£¬Ïß³ÌBҲͬÀí£¬·ÅÈ뻺´æÖеÄÖµÒ²ÊÇ0
  • Á½¸öÏß³Ìͬʱ½øÐÐ×ÔÔö²Ù×÷£¬´ËʱA¡¢BÏ̵߳Ļº´æÖУ¬iµÄÖµ¶¼ÊÇ1
  • Á½¸öÏ߳̽«iдÈëÖ÷Äڴ棬Ï൱ÓÚi±»Á½´Î¸³ÖµÎª1
  • ×îÖÕ½á¹ûÊÇiµÄֵΪ1

Õâ¸ö¾ÍÊǵäÐ͵Ļº´æ²»Ò»ÖÂÎÊÌ⣬Ö÷Á÷µÄ½â¾ö°ì·¨ÓУº

  • ×ÜÏß¼ÓËø
  • »º´æÒ»ÖÂÐÔЭÒé

2.2.1 ×ÜÏß¼ÓËø

ÕâÊÇÒ»ÖÖ±¯¹ÛµÄʵÏÖ·½Ê½£¬¾ßÌåÀ´Ëµ£¬¾ÍÊÇͨ¹ý´¦ÀíÆ÷·¢³ölockÖ¸ÁËøס×ÜÏߣ¬×ÜÏßÊÕµ½Ö¸Áîºó£¬»á×èÈûÆäËû´¦ÀíÆ÷µÄÇëÇó£¬Ö±µ½Õ¼ÓÃËøµÄ´¦ÀíÆ÷Íê³É²Ù×÷¡£ÌصãÊÇÖ»ÓÐÒ»¸öÇÀµ½×ÜÏßËøµÄ´¦ÀíÆ÷ÔËÐУ¬µ«ÊÇÕâÖÖ·½Ê½Ð§ÂʵÍÏ£¬Ò»µ©Ä³¸ö´¦ÀíÆ÷»ñÈ¡µ½ËøÆäËû´¦ÀíÆ÷Ö»ÄÜ×èÈûµÈ´ý£¬»áÓ°Ïì¶àºË´¦ÀíÆ÷µÄÐÔÄÜ¡£

2.2.2 »º´æÒ»ÖÂÐÔЭÒé

ͼʾÈçÏ£º

ÔÚÕâÀï²åÈëͼƬÃèÊö

»º´æÒ»ÖÂÐÔЭÒéÖÐ×î³öÃûµÄ¾ÍÊÇMESIЭÒ飬MESI±£Ö¤ÁËÿһ¸ö»º´æÖÐʹÓõĹ²Ïí±äÁ¿µÄ¸±±¾¶¼ÊÇÒ»Öµġ£´óÖÂ˼ÏëÊÇ£¬CPU²Ù×÷»º´æÖеÄÊý¾Ýʱ£¬Èç¹û·¢ÏָñäÁ¿ÊÇÒ»¸ö¹²Ïí±äÁ¿£¬²Ù×÷ÈçÏ£º

  • ¶ÁÈ¡£º²»×öÆäËû´¦Àí£¬Ö»Êǽ«»º´æÖÐÊý¾Ý¶ÁÈ¡µ½¼Ä´æÆ÷ÖÐ
  • дÈ룺·¢³öÐźÅ֪ͨÆäËûCPU½«¸Ã±äÁ¿µÄ»º´æÐÐÉèÖÃΪÎÞЧ״̬£¨Invalid£©£¬ÆäËûCPU½øÐиñäÁ¿µÄ¶ÁȡʱÐèÒªµ½Ö÷´æÖÐÔٴλñÈ¡

¾ßÌåÀ´Ëµ£¬MESIÖй涨ÁË»º´æÐÐʹÓÃ4ÖÖ״̬±ê¼Ç£º

  • M£ºModified£¬±»ÐÞ¸Ä
  • E£ºExclusive£¬¶ÀÏíµÄ
  • S£ºShared£¬¹²ÏíµÄ
  • I£ºInvalid£¬ÎÞЧµÄ

ÓйØMESIÏêϸµÄʵÏÖ³¬³öÁ˱¾Îĵķ¶Î§£¬ÏëÒªÏêϸÁ˽â¿ÉÒԲο¼´Ë´¦»ò´Ë´¦¡£

3 JMM

¿´ÍêÁËCPU»º´æÔÙÀ´¿´Ò»ÏÂJMM£¬Ò²¾ÍÊÇJavaÄÚ´æÄ£ÐÍ£¬Ö¸¶¨ÁËJVMÈçºÎÓë¼ÆËã»úµÄÖ÷´æ½øÐй¤×÷£¬Í¬Ê±Ò²¾ö¶¨ÁËÒ»¸öÏ̶߳Թ²Ïí±äÁ¿µÄдÈëºÎʱ¶ÔÆäËûÏ߳̿ɼû£¬JMM¶¨ÒåÁËÏ̺߳ÍÖ÷ÄÚ´æÖ®¼äµÄ³éÏó¹Øϵ£¬¾ßÌåÈçÏ£º

  • ¹²Ïí±äÁ¿´æ´¢ÓÚÖ÷ÄÚ´æÖУ¬Ã¿¸öÏ̶߳¼¿ÉÒÔ·ÃÎÊ
  • ÿ¸öÏ̶߳¼ÓÐ˽ÓеŤ×÷ÄÚ´æ»òÕ߽б¾µØÄÚ´æ
  • ¹¤×÷ÄÚ´æÖ»´æ´¢¸ÃÏ̶߳Թ²Ïí±äÁ¿µÄ¸±±¾
  • Ï̲߳»ÄÜÖ±½Ó²Ù×÷Ö÷Äڴ棬ֻÓÐÏȲÙ×÷Á˹¤×÷ÄÚ´æÖ®ºó²ÅÄÜдÈëÖ÷ÄÚ´æ
  • ¹¤×÷ÄÚ´æºÍJMMÄÚ´æÄ£ÐÍÒ»ÑùÒ²ÊÇÒ»¸ö³éÏó¸ÅÄÆäʵ²¢²»´æÔÚ£¬º­¸ÇÁË»º´æ¡¢¼Ä´æÆ÷¡¢±àÒëÆÚÓÅ»¯ÒÔ¼°Ó²¼þµÈ

¼òÂÔͼÈçÏ£º

ÔÚÕâÀï²åÈëͼƬÃèÊö

ÓëMESIÀàËÆ£¬Èç¹ûÒ»¸öÏß³ÌÐÞ¸ÄÁ˹²Ïí±äÁ¿£¬Ë¢Ðµ½Ö÷ÄÚ´æºó£¬ÆäËûÏ̶߳ÁÈ¡¹¤×÷ÄÚ´æµÄʱºò·¢ÏÖ»º´æʧЧ£¬»á´ÓÖ÷ÄÚ´æÔٴζÁÈ¡µ½¹¤×÷ÄÚ´æÖС£

¶øÏÂͼ±íʾÁËJVMÓë¼ÆËã»úÓ²¼þ·ÖÅäµÄ¹Øϵ£º

ÔÚÕâÀï²åÈëͼƬÃèÊö

4 ²¢·¢±à³ÌµÄÈý¸öÌØÐÔ

ÎÄÕ¶¼¿´ÁË´ó°ëÁË»¹Ã»µ½volatile£¿±ð¼±±ð¼±£¬ÏÈÀ´¿´¿´²¢·¢±à³ÌÖеÄÈý¸öÖØÒªÌØÐÔ£¬Õâ¶ÔÕýÈ·Àí½âvolatileÓкܴóµÄ°ïÖú¡£

4.1 Ô­×ÓÐÔ

Ô­×ÓÐÔ¾ÍÊÇÔÚÒ»´Î»ò¶à´Î²Ù×÷ÖУº

  • ҪôËùÓеIJÙ×÷È«²¿¶¼µÃµ½ÁËÖ´ÐУ¬ÇÒ²»»áÊܵ½ÈκÎÒòËصĸÉÈŶøÖжÏ
  • ҪôËùÓеIJÙ×÷¶¼²»Ö´ÐÐ

Ò»¸öµäÐ͵ÄÀý×Ó¾ÍÊÇÁ½¸öÈËתÕË£¬±ÈÈçAÏòBתÕË1000Ôª£¬ÄÇôÕâ°üº¬Á½¸ö»ù±¾µÄ²Ù×÷£º

  • AµÄÕË»§¿Û³ý1000Ôª
  • BµÄÕË»§Ôö¼Ó1000Ôª

ÕâÁ½¸ö²Ù×÷£¬ÒªÃ´¶¼³É¹¦£¬ÒªÃ´¶¼Ê§°Ü£¬Ò²¾ÍÊDz»ÄܳöÏÖAÕË»§¿Û³ý1000µ«ÊÇBÕË»§½ð¶î²»±äµÄÇé¿ö£¬Ò²²»ÄܳöÏÖAÕË»§½ð¶î²»±äBÕË»§Ôö¼Ó1000µÄÇé¿ö¡£

ÐèҪעÒâµÄÊÇÁ½¸öÔ­×ÓÐÔ²Ù×÷½áºÏÔÚÒ»Æðδ±ØÊÇÔ­×ÓÐԵģ¬±ÈÈçi++¡£±¾ÖÊÉÏÀ´Ëµ£¬i++Éæ¼°µ½ÁËÈý¸ö²Ù×÷£º

  • get i
  • i+1
  • set i

ÕâÈý¸ö²Ù×÷¶¼ÊÇÔ­×ÓÐԵģ¬µ«ÊÇ×éºÏÔÚÒ»Æð£¨i++£©¾Í²»ÊÇÔ­×ÓÐԵġ£

4.2 ¿É¼ûÐÔ

ÁíÒ»¸öÖØÒªµÄÌØÐÔÊǿɼûÐÔ£¬¿É¼ûÐÔÊÇÖ¸£¬Ò»¸öÏ̶߳Թ²Ïí±äÁ¿½øÐÐÁËÐ޸ģ¬ÄÇôÁíÍâµÄÏ߳̿ÉÒÔÁ¢¼´¿´µ½Ð޸ĺóµÄ×îÐÂÖµ¡£

Ò»¸ö¼òµ¥µÄÀý×ÓÈçÏ£º

public class Main {
    private int x = 0;
    private static final int MAX = 100000;
    public static void main(String[] args) throws InterruptedException {
        Main m = new Main();
        Thread thread0 = new Thread(()->{
            while(m.x < MAX) {
                ++m.x;
            }
        });

        Thread thread1 = new Thread(()->{
            while(m.x < MAX){
            }
            System.out.println("finish");
        });

        thread1.start();
        TimeUnit.MILLISECONDS.sleep(1);
        thread0.start();
    }
}

Ïß³Ìthread1»áÒ»Ö±ÔËÐУ¬ÒòΪthread1°Ñx¶ÁÈ빤×÷ÄÚ´æºó£¬»áÒ»Ö±ÅжϹ¤×÷ÄÚ´æÖеÄÖµ£¬ÓÉÓÚthread0¸Ä±äµÄÊÇthread0¹¤×÷ÄÚ´æµÄÖµ£¬²¢Ã»ÓжÔthread1¿É¼û£¬Òò´ËÓÀÔ¶Ò²²»»áÊä³öfinish£¬Ê¹ÓÃjstackÒ²¿ÉÒÔ¿´µ½½á¹û£º

ÔÚÕâÀï²åÈëͼƬÃèÊö

4.3 ÓÐÐòÐÔ

ÓÐÐòÐÔÊÇÖ¸´úÂëÔÚÖ´Ðйý³ÌÖеÄÏȺó˳Ðò£¬ÓÉÓÚJVMµÄÓÅ»¯£¬µ¼ÖÂÁË´úÂëµÄ±àд˳Ðòδ±ØÊÇ´úÂëµÄÔËÐÐ˳Ðò£¬±ÈÈçÏÂÃæµÄËÄÌõÓï¾ä£º

int x = 10;
int y = 0;
x++;
y = 20;

ÓпÉÄÜy=20ÔÚx++Ç°Ö´ÐУ¬Õâ¾ÍÊÇÖ¸ÁîÖØÅÅÐò¡£Ò»°ãÀ´Ëµ£¬´¦ÀíÆ÷ΪÁËÌá¸ß³ÌÐòµÄЧÂÊ£¬¿ÉÄÜ»á¶ÔÊäÈëµÄ´úÂëÖ¸Áî×öÒ»¶¨µÄÓÅ»¯£¬²»»áÑϸñ°´ÕÕ±àд˳ÐòÈ¥Ö´ÐдúÂ룬µ«¿ÉÒÔ±£Ö¤×îÖÕÔËËã½á¹ûÊDZàÂëʱµÄÆÚÍû½á¹û£¬µ±È»£¬ÖØÅÅÐòÒ²ÓÐÒ»¶¨µÄ¹æÔò£¬ÐèÒªÑϸñ×ñÊØÖ¸ÁîÖ®¼äµÄÊý¾ÝÒÀÀµ¹Øϵ£¬²¢²»ÊÇ¿ÉÒÔÈÎÒâÖØÅÅÐò£¬±ÈÈ磺

int x = 10;
int y = 0;
x++;
y = x+1;

y=x+1¾Í²»ÄÜÏÈÓÅÓÚx++Ö´ÐС£

ÔÚµ¥Ïß³ÌÏÂÖØÅÅÐò²»»áµ¼ÖÂÔ¤ÆÚÖµµÄ¸Ä±ä£¬µ«ÔÚ¶àÏß³ÌÏ£¬Èç¹ûÓÐÐòÐԵò»µ½±£Ö¤£¬ÄÇô½«¿ÉÄܳöÏֺܴóµÄÎÊÌ⣺

private boolean initialized = false;
private Context context;
public Context load(){
    if(!initialized){
        context = loadContext();
        initialized = true;
    }
    return context;
}

Èç¹û·¢ÉúÁËÖØÅÅÐò£¬initialized=trueÅÅÐòµ½ÁËcontext=loadContext()µÄÇ°Ã棬¼ÙÉèÁ½¸öÏß³ÌA¡¢Bͬʱ·ÃÎÊ£¬ÇÒloadContext()ÐèÒªÒ»¶¨ºÄʱ£¬ÄÇô£º

  • Ïß³ÌAͨ¹ýÅжϺó£¬ÏÈÉèÖò¼¶û±äÁ¿µÄֵΪtrue£¬ÔÙ½øÐÐloadContext()²Ù×÷
  • Ïß³ÌBÖÐÓÉÓÚ²¼¶û±äÁ¿±»ÉèÖÃΪtrue£¬»áÖ±½Ó·µ»ØÒ»¸öδ¼ÓÔØÍê³ÉµÄcontext

5 volatile

ºÃÁËÖÕÓÚµ½ÁËvolatileÁË£¬Ç°Ãæ˵ÁËÕâô¶à£¬Ä¿µÄ¾ÍÊÇΪÁËÄܳ¹µ×Àí½âºÍÃ÷°×volatile¡£Õⲿ·Ö·ÖΪËĸöС½Ú£º

  • volatileµÄÓïÒå
  • ÈçºÎ±£Ö¤ÓÐÐòÐÔÒÔ¼°¿É¼ûÐÔ
  • ʵÏÖÔ­Àí
  • ʹÓó¡¾°
  • ÓësynchronizedÇø±ð

ÏÈÀ´½éÉÜÒ»ÏÂvolatileµÄÓïÒå¡£

5.1 ÓïÒå

±»volatileÐÞÊεÄʵÀý±äÁ¿»òÕßÀà±äÁ¿¾ßÓÐÁ½²ãÓïÒ壺

  • ±£Ö¤Á˲»Í¬Ïß³ÌÖ®¼ä¶Ô¹²Ïí±äÁ¿²Ù×÷ʱµÄ¿É¼ûÐÔ
  • ½ûÖ¹¶ÔÖ¸Áî½øÐÐÖØÅÅÐò²Ù×÷

5.2 ÈçºÎ±£Ö¤¿É¼ûÐÔÒÔ¼°ÓÐÐòÐÔ

ÏÈ˵½áÂÛ£º

  • volatileÄܱ£Ö¤¿É¼ûÐÔ
  • volatileÄܱ£Ö¤ÓÐÐòÐÔ
  • volatile²»Äܱ£Ö¤Ô­×ÓÐÔ

ÏÂÃæ·Ö±ð½øÐнéÉÜ¡£

5.2.1 ¿É¼ûÐÔ

JavaÖб£Ö¤¿É¼ûÐÔÓÐÈçÏ·½Ê½£º

  • volatile£ºµ±Ò»¸ö±äÁ¿±»volatileÐÞÊÎʱ£¬¶Ô¹²Ïí×ÊÔ´µÄ¶Á²Ù×÷»áÖ±½ÓÔÚÖ÷ÄÚ´æÖнøÐУ¨×¼È·À´ËµÒ²»á¶ÁÈ¡µ½¹¤×÷ÄÚ´æÖУ¬µ«ÊÇÈç¹ûÆäËûÏ߳̽øÐÐÁËÐ޸ľͱØÐë´ÓÖ÷ÄÚ´æÖØжÁÈ¡£©£¬Ð´²Ù×÷ÊÇÏÈÐ޸Ť×÷Äڴ棬µ«ÊÇÐ޸ĽáÊøºóÁ¢¼´Ë¢Ðµ½Ö÷ÄÚ´æÖÐ
  • synchronized£ºsynchronizedÒ»ÑùÄܱ£Ö¤¿É¼ûÐÔ£¬Äܹ»±£Ö¤Í¬Ò»Ê±¿ÌÖ»ÓÐÒ»¸öÏ̻߳ñÈ¡µ½Ëø£¬È»ºóÖ´ÐÐͬ²½·½·¨£¬²¢ÇÒÈ·±£ËøÊÍ·Å֮ǰ£¬±äÁ¿µÄÐ޸ı»Ë¢Ðµ½Ö÷ÄÚ´æÖÐ
  • ʹÓÃÏÔʽËøLock£ºLockµÄlock·½·¨Äܱ£Ö¤Í¬Ò»Ê±¿ÌÖ»ÓÐÒ»¸öÏß³ÌÄܹ»»ñÈ¡µ½ËøÈ»ºóÖ´ÐÐͬ²½·½·¨£¬²¢ÇÒÈ·±£ËøÊÍ·Å֮ǰÄܹ»½«¶Ô±äÁ¿µÄÐÞ¸Äˢе½Ö÷ÄÚ´æÖÐ

¾ßÌåÀ´Ëµ£¬¿ÉÒÔ¿´Ò»ÏÂ֮ǰµÄÀý×Ó£º

public class Main {
    private int x = 0;
    private static final int MAX = 100000;
    public static void main(String[] args) throws InterruptedException {
        Main m = new Main();
        Thread thread0 = new Thread(()->{
            while(m.x < MAX) {
                ++m.x;
            }
        });

        Thread thread1 = new Thread(()->{
            while(m.x < MAX){
            }
            System.out.println("finish");
        });

        thread1.start();
        TimeUnit.MILLISECONDS.sleep(1);
        thread0.start();
    }
}

ÉÏÃæ˵¹ýÕâ¶Î´úÂë»á²»¶ÏÔËÐУ¬Ò»Ö±Ã»ÓÐÊä³ö£¬¾ÍÊÇÒòΪÐ޸ĺóµÄx¶ÔÏß³Ìthread1²»¿É¼û£¬Èç¹ûÔÚxµÄ¶¨ÒåÖмÓÉÏÁËvolatile£¬¾Í²»»á³öÏÖûÓÐÊä³öµÄÇé¿öÁË£¬ÒòΪ´Ëʱ¶ÔxµÄÐÞ¸ÄÊÇÏß³Ìthread1¿É¼ûµÄ¡£

5.2.2 ÓÐÐòÐÔ

JMMÖÐÔÊÐí±àÒëÆںʹ¦ÀíÆ÷¶ÔÖ¸Áî½øÐÐÖØÅÅÐò£¬ÔÚ¶àÏ̵߳ÄÇé¿öÏÂÓпÉÄÜ»á³öÏÖÎÊÌ⣬Ϊ´Ë£¬JavaͬÑùÌṩÁËÈýÖÖ»úÖÆÈ¥±£Ö¤ÓÐÐòÐÔ£º

  • volatile
  • synchronized
  • ÏÔʽËøLock

ÁíÍ⣬¹ØÓÚÓÐÐòÐÔ²»µÃ²»ÌáµÄ¾ÍÊÇHappens-beforeÔ­Ôò¡£Happends-beforeÔ­Ôò˵µÄ¾ÍÊÇÈç¹ûÁ½¸ö²Ù×÷µÄÖ´ÐдÎÐòÎÞ·¨´Ó¸ÃÔ­ÔòÍƵ¼³öÀ´£¬ÄÇô¾ÍÎÞ·¨±£Ö¤ÓÐÐòÐÔ£¬JVM»ò´¦ÀíÆ÷¿ÉÒÔÈÎÒâÖØÅÅÐò¡£Õâô×öµÄÄ¿µÄÊÇΪÁ˾¡¿ÉÄÜÌá¸ß³ÌÐòµÄ²¢Ðжȣ¬¾ßÌå¹æÔòÈçÏ£º

  • ³ÌÐò´ÎÐò¹æÔò£ºÔÚÒ»¸öÏß³ÌÄÚ£¬´úÂë°´ÕÕ±àдʱµÄ´ÎÐòÖ´ÐУ¬±àдÔÚºóÃæµÄ²Ù×÷·¢ÉúÓë±àдÔÚÇ°ÃæµÄ²Ù×÷Ö®ºó
  • Ëø¶¨¹æÔò£ºÈç¹ûÒ»¸öËø´¦ÓÚËø¶¨×´Ì¬£¬Ôòunlock²Ù×÷ÒªÏÈÐз¢ÉúÓÚ¶Ôͬһ¸öËøµÄlock²Ù×÷
  • volatile±äÁ¿¹æÔò£º¶ÔÒ»¸ö±äÁ¿µÄд²Ù×÷ÒªÔçÓÚ¶ÔÕâ¸ö±äÁ¿Ö®ºóµÄ¶Á²Ù×÷
  • ´«µÝ¹æÔò£ºÈç¹û²Ù×÷AÏÈÓÚ²Ù×÷B£¬²Ù×÷BÏÈÓÚ²Ù×÷C£¬ÄÇô²Ù×÷AÏÈÓÚ²Ù×÷C
  • Ïß³ÌÆô¶¯¹æÔò£ºThread¶ÔÏóµÄstart()·½·¨ÏÈÐз¢ÉúÓÚ¶Ô¸ÃÏ̵߳ÄÈκζ¯×÷
  • Ïß³ÌÖжϹæÔò£º¶ÔÏß³ÌÖ´ÐÐinterrupt()·½·¨¿Ï¶¨ÒªÓÅÓÚ²¶»ñµ½ÖжÏÐźţ¬»»¾ä»°Ëµ£¬Èç¹ûÊÕµ½ÁËÖжÏÐźţ¬ÄÇôÔÚ´Ë֮ǰ±Ø¶¨µ÷ÓÃÁËinterrupt()
  • Ïß³ÌÖÕ½á¹æÔò£ºÏß³ÌÖÐËùÓвÙ×÷¶¼ÒªÏÈÐз¢ÉúÓÚÏ̵߳ÄÖÕÖ¹¼ì²â£¬Ò²¾ÍÊÇÂß¼­µ¥ÔªµÄÖ´Ðп϶¨Òª·¢ÉúÓÚÏß³ÌÖÕֹ֮ǰ
  • ¶ÔÏóÖÕ½á¹æÔò£ºÒ»¸ö¶ÔÏó³õʼ»¯µÄÍê³ÉÏÈÐз¢ÉúÓÚfinalize()֮ǰ

¶ÔÓÚvolatile£¬»áÖ±½Ó½ûÖ¹¶ÔÖ¸ÁîÖØÅÅ£¬µ«ÊǶÔÓÚvolatileÇ°ºóÎÞÒÀÀµ¹ØϵµÄÖ¸Áî¿ÉÒÔËæÒâÖØÅÅ£¬±ÈÈ磺

int x = 0;
int y = 1;
//private volatile int z;
z = 20;
x++;
y--;

ÔÚz=20֮ǰ£¬Ïȶ¨Òåx»òÏȶ¨Òåy²¢Ã»ÓÐÒªÇó£¬Ö»ÐèÒªÔÚÖ´ÐÐz=20µÄʱºò£¬¿ÉÒÔ±£Ö¤x=0,y=1¼´¿É£¬Í¬Àí£¬x++»òy--¾ßÌåÏÈÖ´ÐÐÄÄÒ»¸ö²¢Ã»ÓÐÒªÇó£¬Ö»ÐèÒª±£Ö¤Á½ÕßÖ´ÐÐÔÚz=20Ö®ºó¼´¿É¡£

5.2.3 Ô­×ÓÐÔ

ÔÚJavaÖУ¬ËùÓжԻù±¾Êý¾ÝÀàÐͱäÁ¿µÄ¶ÁÈ¡¸³Öµ²Ù×÷¶¼ÊÇÔ­×ÓÐԵģ¬¶ÔÒýÓÃÀàÐ͵ıäÁ¿¶ÁÈ¡ºÍ¸³ÖµÒ²ÊÇÔ­×ÓÐԵģ¬µ«ÊÇ£º

  • ½«Ò»¸ö±äÁ¿¸³Öµ¸øÁíÒ»¸ö±äÁ¿µÄ²Ù×÷²»ÊÇÔ­×ÓÐԵģ¬ÒòΪÉæ¼°µ½ÁËÒ»¸ö±äÁ¿µÄ¶ÁÈ¡ÒÔ¼°Ò»¸ö±äÁ¿µÄдÈ룬Á½¸öÔ­×ÓÐÔ²Ù×÷½áºÏÔÚÒ»Æð¾Í²»ÊÇÔ­×ÓÐÔ²Ù×÷
  • ¶à¸öÔ­×ÓÐÔ²Ù×÷ÔÚÒ»Æð¾Í²»ÊÇÔ­×ÓÐÔ²Ù×÷£¬±ÈÈçi++
  • JMMÖ»±£Ö¤»ù±¾¶ÁÈ¡ºÍ¸³ÖµµÄÔ­×ÓÐÔ²Ù×÷£¬ÆäËûµÄ¾ù²»±£Ö¤£¬Èç¹ûÐèÒª¾ß±¸Ô­×ÓÐÔ£¬ÄÇô¿ÉÒÔʹÓÃsynchronized»òLock£¬»òÕßJUC°üϵÄÔ­×Ó²Ù×÷Àà

Ò²¾ÍÊÇ˵£¬volatile²¢²»Äܱ£Ö¤Ô­×ÓÐÔ£¬Àý×ÓÈçÏ£º

public class Main {
    private volatile int x = 0;
    private static final CountDownLatch latch = new CountDownLatch(10);

    public void inc() {
        ++x;
    }

    public static void main(String[] args) throws InterruptedException {
        Main m = new Main();
        IntStream.range(0, 10).forEach(i -> {
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    m.inc();
                }
                latch.countDown();
            }).start();
        });
        latch.await();
        System.out.println(m.x);
    }
}

×îºóÊä³öµÄxµÄÖµ»áÉÙÓÚ10000£¬¶øÇÒÿ´ÎÔËÐеĽá¹ûÒ²²¢²»Ïàͬ£¬ÖÁÓÚÔ­Òò£¬¿ÉÒÔ´ÓÁ½¸öÏß³ÌA¡¢B¿ªÊ¼·ÖÎö£¬Í¼Ê¾ÈçÏ£º

ÔÚÕâÀï²åÈëͼƬÃèÊö

  • 0-t1£ºÏß³ÌA½«x¶ÁÈ빤×÷Äڴ棬´Ëʱx=0
  • t1-t2£ºÏß³ÌAʱ¼äƬÍ꣬CPUµ÷¶ÈÏß³ÌB£¬Ïß³ÌB½«x¶ÁÈ빤×÷Äڴ棬´Ëʱx=0
  • t2-t3£ºÏß³ÌB¶Ô¹¤×÷ÄÚ´æÖеÄx½øÐÐ×ÔÔö²Ù×÷£¬²¢¸üе½¹¤×÷ÄÚ´æÖÐ
  • t3-t4£ºÏß³ÌBʱ¼äƬÍ꣬CPUµ÷¶ÈÏß³ÌA£¬Í¬ÀíÏß³ÌA¶Ô¹¤×÷ÄÚ´æÖеÄx×ÔÔö
  • t4-t5£ºÏß³ÌA½«¹¤×÷ÄÚ´æÖеÄֵд»ØÖ÷Äڴ棬´ËʱÖ÷ÄÚ´æÖеÄֵΪx=1
  • t5ÒÔºó£ºÏß³ÌAʱ¼äƬÍ꣬CPUµ÷¶ÈÏß³ÌB£¬Ïß³ÌBÒ²½«×Ô¼ºµÄ¹¤×÷ÄÚ´æд»ØÖ÷Äڴ棬Ôٴν«Ö÷ÄÚ´æÖеÄx¸³ÖµÎª1

Ò²¾ÍÊÇ˵£¬¶àÏ̲߳Ù×÷µÄ»°£¬»á³öÏÖÁ½´Î×ÔÔöµ«ÊÇʵ¼ÊÉÏÖ»½øÐÐÒ»´ÎÊýÖµÐ޸ĵIJÙ×÷¡£ÏëÒªxµÄÖµ±äΪ10000Ò²ºÜ¼òµ¥£¬¼ÓÉÏsynchronized¼´¿É£º

new Thread(() -> {
    synchronized (m) {
        for (int j = 0; j < 1000; j++) {
            m.inc();
        }
    }
    latch.countDown();
}).start();

5.3 ʵÏÖÔ­Àí

Ç°ÃæÒѾ­ÖªµÀ£¬volatile¿ÉÒÔ±£Ö¤ÓÐÐòÐÔÒÔ¼°¿É¼ûÐÔ£¬ÄÇô£¬¾ßÌåÊÇÈçºÎ²Ù×÷µÄÄØ£¿

´ð°¸¾ÍÊÇÒ»¸ölock;ǰ׺£¬¸Ãǰ׺ʵ¼ÊÉÏÏ൱ÓÚÒ»¸öÄÚ´æÆÁÕÏ£¬¸ÃÄÚ´æÆÁÕÏ»áΪָÁîµÄÖ´ÐÐÌṩÈçϼ¸¸ö±£ÕÏ£º

  • È·±£Ö¸ÁîÖØÅÅÐòʱ²»»á½«ÆäºóÃæµÄ´úÂëÅŵ½ÄÚ´æÆÁÕÏ֮ǰ
  • È·±£Ö¸ÁîÖØÅÅÐòʱ²»»á½«ÆäÇ°ÃæµÄ´úÂëÅŵ½ÄÚ´æÆÁÕÏÖ®ºó
  • È·±£Ö´Ðе½ÄÚ´æÆÁÕÏÐÞÊεÄÖ¸ÁîʱǰÃæµÄ´úÂëÈ«²¿Ö´ÐÐÍê³É
  • Ç¿Öƽ«Ï̹߳¤×÷ÄÚ´æÖеÄÖµÐÞ¸Äˢе½Ö÷´æÖÐ
  • Èç¹ûÊÇд²Ù×÷£¬»áµ¼ÖÂÆäËûÏ̹߳¤×÷ÄÚ´æÖеĻº´æÊý¾ÝʧЧ

5.4 ʹÓó¡¾°

Ò»¸öµäÐ͵ÄʹÓó¡¾°ÊÇÀûÓÿª¹Ø½øÐÐÏ̵߳ĹرղÙ×÷£¬Àý×ÓÈçÏ£º

public class ThreadTest extends Thread{
    private volatile boolean started = true;

    @Override
    public void run() {
        while (started){
            
        }
    }

    public void shutdown(){
        this.started = false;
    }
}

Èç¹û²¼¶û±äÁ¿Ã»Óб»volatileÐÞÊΣ¬ÄÇôºÜ¿ÉÄÜеIJ¼¶ûֵˢв»µ½Ö÷ÄÚ´æÖУ¬µ¼ÖÂÏ̲߳»»á½áÊø¡£

5.5 ÓësynchronizedµÄÇø±ð

  • ʹÓÃÉϵÄÇø±ð£ºvolatileÖ»ÄÜÓÃÓÚÐÞÊÎʵÀý±äÁ¿»òÕßÀà±äÁ¿£¬µ«ÊDz»ÄÜÓÃÓÚÐÞÊη½·¨¡¢·½·¨²ÎÊý¡¢¾Ö²¿±äÁ¿µÈ£¬ÁíÍâ¿ÉÒÔÐÞÊεıäÁ¿Îªnull¡£µ«synchronized²»ÄÜÓÃÓÚ¶Ô±äÁ¿µÄÐÞÊΣ¬Ö»ÄÜÐÞÊη½·¨»òÓï¾ä¿é£¬¶øÇÒmonitor¶ÔÏó²»ÄÜΪnull
  • ¶ÔÔ­×ÓÐԵı£Ö¤£ºvolatileÎÞ·¨±£Ö¤Ô­×ÓÐÔ£¬µ«ÊÇsynchronized¿ÉÒÔ±£Ö¤
  • ¶Ô¿É¼ûÐԵı£Ö¤£ºvolatileÓësynchronized¶¼Äܱ£Ö¤¿É¼ûÐÔ£¬µ«ÊÇsynchronizedÊǽèÖúÓÚJVMÖ¸Áîmonitor enter/monitor exit±£Ö¤µÄ£¬ÔÚmonitor exitµÄʱºòËùÓй²Ïí×ÊÔ´¶¼±»Ë¢Ðµ½Ö÷ÄÚ´æÖУ¬¶øvolatileÊÇͨ¹ýlock;»úÆ÷Ö¸ÁîʵÏֵģ¬ÆÈʹÆäËûÏ̹߳¤×÷ÄÚ´æʧЧ£¬ÐèÒªµ½Ö÷ÄÚ´æ¼ÓÔØ
  • ¶ÔÓÐÐòÐԵı£Ö¤£ºvolatileÄܹ»½ûÖ¹JVMÒÔ¼°´¦ÀíÆ÷¶ÔÆä½øÐÐÖØÅÅÐò£¬¶øsynchronized±£Ö¤µÄÓÐÐòÐÔÊÇͨ¹ý³ÌÐò´®Ðл¯Ö´Ðл»À´µÄ£¬²¢ÇÒÔÚsynchronized´úÂë¿éÖеĴúÂëÒ²»á·¢ÉúÖ¸ÁîÖØÅŵÄÇé¿ö
  • ÆäËûÇø±ð£ºvolatile²»»áʹÏß³ÌÏÝÈë×èÈû£¬µ«synchronized»á

±¾ÎÄת×ÔÍøÂ磬°æȨ¹éÔ­×÷ÕßËùÓУ¬Ô­ÎÄÁ´½Ó£ºhttps://segmentfault.com/a/1190000040008866
±¾Õ¾²¿·ÖÄÚÈÝתÔØÓÚÍøÂ磬°æȨ¹éÔ­×÷ÕßËùÓУ¬×ªÔØ֮ĿµÄÔÚÓÚ´«²¥¸ü¶àÓÅÐã¼¼ÊõÄÚÈÝ£¬ÈçÓÐÇÖȨÇëÁªÏµQQ/΢ÐÅ£º153890879ɾ³ý£¬Ð»Ð»£¡

ÍƼöͼÎÄ

  • ÖÜÅÅÐÐ
  • ÔÂÅÅÐÐ
  • ×ÜÅÅÐÐ

Ëæ»úÍƼö