国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

慕課網(wǎng)_《細(xì)說(shuō)Java多線程之內(nèi)存可見(jiàn)性》學(xué)習(xí)總結(jié)

wupengyu / 3259人閱讀

時(shí)間:2017年07月09日星期日
說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com
教學(xué)源碼:無(wú)
學(xué)習(xí)源碼:https://github.com/zccodere/s...

第一章:課程簡(jiǎn)介 1-1 課程簡(jiǎn)介

課程目標(biāo)和學(xué)習(xí)內(nèi)容

共享變量在線程間的可見(jiàn)性
synchronized實(shí)現(xiàn)可見(jiàn)性
volatile實(shí)現(xiàn)可見(jiàn)性
    指令重排序
    as-if-serial語(yǔ)義
    volatile使用注意事項(xiàng)
synchronized和volatile比較
第二章:可見(jiàn)性介紹 2-1 可見(jiàn)性介紹

可見(jiàn)性

一個(gè)線程對(duì)共享變量值的修改,能夠及時(shí)地被其他線程看到

共享變量

如果一個(gè)變量在多個(gè)線程的工作內(nèi)存中都存在副本,那么這個(gè)變量就是這幾個(gè)線程的共享變量

Java內(nèi)存模型(JMM)

Java內(nèi)存模型(Java Memory Model)描述了Java程序中各種變量(線程共享變量)的訪問(wèn)規(guī)則,以及在JVM中將變量存儲(chǔ)到內(nèi)存和從內(nèi)存中讀取出變量這樣的底層細(xì)節(jié)

Java內(nèi)存模型

所有的變量都存儲(chǔ)在主內(nèi)存中
每個(gè)線程都有自己獨(dú)立的工作內(nèi)存,里面保存該線程使用到的變量的副本
(主內(nèi)存中該變量的一份拷貝)

Java內(nèi)存模型示意圖

Java內(nèi)存模型中的兩條規(guī)定

線程對(duì)共享變量的所有操作都必須在自己的工作內(nèi)存中進(jìn)行,不能直接從主內(nèi)存中讀寫(xiě)
不同線程之間無(wú)法直接訪問(wèn)其他線程工作內(nèi)存中的變量,線程間變量值的傳遞需要通過(guò)主內(nèi)存來(lái)完成

共享變量可見(jiàn)性實(shí)現(xiàn)的原理。如線程1對(duì)共享變量的修改要想被線程2及時(shí)看到,必須要經(jīng)過(guò)如下2個(gè)步驟

把工作內(nèi)存1中更新過(guò)的共享變量刷新到主內(nèi)存中
將主內(nèi)存中最新的共享變量的值更新到工作內(nèi)存2中

共享變量可見(jiàn)性實(shí)現(xiàn)的原理示意圖

第三章:synchronized實(shí)現(xiàn)可見(jiàn)性 3-1 synchronized實(shí)現(xiàn)可見(jiàn)性原理

要實(shí)現(xiàn)共享變量的可見(jiàn)性,必須保證兩點(diǎn)

線程修改后的共享變量能夠及時(shí)從工作內(nèi)存刷新到主內(nèi)存中
其他線程能夠及時(shí)把共享變量的最新值從主內(nèi)存更新到自己的工作內(nèi)存中

Java語(yǔ)言層面支持的可見(jiàn)性實(shí)現(xiàn)方式

synchronized
volatile

synchronized能夠?qū)崿F(xiàn)

原子性(同步)
可見(jiàn)性

JMM關(guān)于synchronized的兩條規(guī)定

線程解鎖前,必須把共享變量的最新值刷新到主內(nèi)存中
線程加鎖時(shí),將清空工作內(nèi)存中共享變量的值,從而使用共享變量時(shí)需要從主內(nèi)存中重新讀取最新的值
(注意:加鎖與解鎖需要時(shí)同一把鎖)

線程解鎖前對(duì)共享變量的修改在下次加鎖時(shí)對(duì)其他線程可見(jiàn)

線程執(zhí)行互斥代碼的過(guò)程

1.獲得互斥鎖
2.清空工作內(nèi)存
3.從主內(nèi)存拷貝變量的最新副本到工作內(nèi)存
4.執(zhí)行代碼
5.將更改后的共享變量的值刷新到主內(nèi)存
6.釋放互斥鎖

重排序

代碼書(shū)寫(xiě)的順序與實(shí)際執(zhí)行的順序不同,指令重排序是編譯器或處理器為了提高程序性能而做的優(yōu)化

當(dāng)前的三種重排序

編譯器優(yōu)化的重排序(編譯器優(yōu)化)
指令級(jí)并行重排序(處理器優(yōu)化)
內(nèi)存系統(tǒng)的重排序(處理器優(yōu)化)

重排序示意圖:有可能出現(xiàn)下面情況

as-if-serial

無(wú)論如何重排序,程序執(zhí)行的結(jié)果應(yīng)該與代碼順序執(zhí)行的結(jié)果一致(Java編譯器、運(yùn)行時(shí)和處理器都會(huì)保證Java在單線程下遵循as-if-serial語(yǔ)義)

3-2 synchronized實(shí)現(xiàn)可見(jiàn)性(上)

代碼演示:

package com.myimooc.synchronizeddemo.my;

/**
 * 程序主類(lèi)
 * @author ZhangCheng on 2017-07-09
 *
 */
public class SynchronizedDemo {
    
    //共享變量
    private boolean ready = false;
    private int result = 0;
    private int number = 1;   
    //寫(xiě)操作
    public synchronized void write(){
        ready = true;                           //1.1                
        number = 2;                            //1.2                
    }
    //讀操作
    public synchronized void read(){                    
        if(ready){                             //2.1
            result = number*3;         //2.2
        }       
        System.out.println("result的值為:" + result);
    }

    //內(nèi)部線程類(lèi)
    private class ReadWriteThread extends Thread {
        //根據(jù)構(gòu)造方法中傳入的flag參數(shù),確定線程執(zhí)行讀操作還是寫(xiě)操作
        private boolean flag;
        public ReadWriteThread(boolean flag){
            this.flag = flag;
        }
        @Override                                                                    
        public void run() {
            if(flag){
                //構(gòu)造方法中傳入true,執(zhí)行寫(xiě)操作
                write();
            }else{
                //構(gòu)造方法中傳入false,執(zhí)行讀操作
                read();
            }
        }
    }

    public static void main(String[] args)  {
        SynchronizedDemo synDemo = new SynchronizedDemo();
        //啟動(dòng)線程執(zhí)行寫(xiě)操作
        synDemo.new ReadWriteThread(true).start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //啟動(dòng)線程執(zhí)行讀操作
        synDemo.new ReadWriteThread(false).start();
    }
    
}
3-3 synchronized實(shí)現(xiàn)可見(jiàn)性(中)

導(dǎo)致共享變量在線程間不可見(jiàn)的原因

線程的交叉執(zhí)行
重排序結(jié)合線程交叉執(zhí)行
共享變量更新后的值沒(méi)有在工作內(nèi)存與主內(nèi)存間及時(shí)更新

安全的代碼

3-4 synchronized實(shí)現(xiàn)可見(jiàn)性(下)

第四章:volatile實(shí)現(xiàn)可見(jiàn)性 4-1 volatile能夠保證可見(jiàn)性

volatile關(guān)鍵字

能夠保證volatile變量的可見(jiàn)性
不能保證volatile變量復(fù)合操作的原子性

volatile如何實(shí)現(xiàn)內(nèi)存可見(jiàn)性

深入來(lái)說(shuō):通過(guò)加入內(nèi)存屏障和禁止重排序優(yōu)化來(lái)實(shí)現(xiàn)的
    對(duì)volatile變量執(zhí)行寫(xiě)操作時(shí),會(huì)在寫(xiě)操作后加入一個(gè)store屏障指令
    對(duì)volatile變量執(zhí)行讀操作時(shí),會(huì)在讀操作前加入一條load屏障指令
通俗地講:volatile變量在每次被線程訪問(wèn)時(shí),都強(qiáng)迫從主內(nèi)存中重讀該變量的值,
    而當(dāng)該變量發(fā)生變化時(shí),又會(huì)強(qiáng)迫線程將最新的值刷新到主內(nèi)存。
    這樣任何時(shí)刻,不同的線程總能看到該變量的最新值

線程寫(xiě)volatile變量的過(guò)程

改變線程工作內(nèi)存中volatile變量副本的值
將改變后的副本的值從工作內(nèi)存刷新到主內(nèi)存

線程讀volatile變量的過(guò)程

從主內(nèi)存中讀取volatile變量的最新值到線程的工作內(nèi)存中
從工作內(nèi)存中讀取volatile變量的副本
4-2 volatile不能保證原子性(上)

代碼演示:

package com.myimooc.volatiledemo.my;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 程序主類(lèi)
 * @author ZhangCheng on 2017-07-09
 *
 */
public class VolatileDemo {
    
    private int number = 0;
    
    public int getNumber(){
        return this.number;
    }
    
    public void increase(){
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        this.number++;
    }
    
    public static void main(String[] args) {
        final VolatileDemo volDemo = new VolatileDemo();
        for(int i = 0 ; i < 500 ; i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    volDemo.increase();
                }
            }).start();
        }
        
        //如果還有子線程在運(yùn)行,主線程就讓出CPU資源,
        //直到所有的子線程都運(yùn)行完了,主線程再繼續(xù)往下執(zhí)行
        while(Thread.activeCount() > 1){
            Thread.yield();
        }
        
        System.out.println("number : " + volDemo.getNumber());
    }
    
}
4-3 volatile不能保證原子性(中)

程序分析

解決方案:保證number自增操作的原子性

使用synchronized關(guān)鍵字
使用ReentrantLock(java.util.concurrent.locks包下)
使用AtomicInterger(java.util.concurrent.atomic包下)
4-4 volatile不能保證原子性(下)

代碼演示:

package com.myimooc.volatiledemo.my;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 程序主類(lèi)
 * @author ZhangCheng on 2017-07-09
 *
 */
public class VolatileDemo {
    
    private int number = 0;
    private Lock lock = new ReentrantLock();
    
    public int getNumber(){
        return this.number;
    }
    
    public void increase(){
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        // 方案一
        /*
        synchronized(this){
            this.number++;
        }
        */
        // 方案二
        lock.lock();// 獲取鎖
        try {
            this.number++;
        } finally {
            lock.unlock();// 釋放鎖
        }
        
    }
    
    public static void main(String[] args) {
        final VolatileDemo volDemo = new VolatileDemo();
        for(int i = 0 ; i < 500 ; i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    volDemo.increase();
                }
            }).start();
        }
        
        //如果還有子線程在運(yùn)行,主線程就讓出CPU資源,
        //直到所有的子線程都運(yùn)行完了,主線程再繼續(xù)往下執(zhí)行
        while(Thread.activeCount() > 1){
            Thread.yield();
        }
        
        System.out.println("number : " + volDemo.getNumber());
    }
    
}
4-5 volatile使用注意事項(xiàng)

volatile適用場(chǎng)合:要在多線程中安全的使用volatile變量,必須同時(shí)滿(mǎn)足

對(duì)變量的寫(xiě)入操作不依賴(lài)其當(dāng)前值
    不滿(mǎn)足:number++、count = count * 5等
    滿(mǎn)足:boolean變量、記錄溫度變化的變量等
該變量沒(méi)有包含在具有其他變量的不變式中
    不滿(mǎn)足:不變式low < up
4-6 synchronized和volatile比較

synchronized和volatile比較

volatile不需要加鎖,比synchronized更輕量級(jí),不會(huì)阻塞線程
從內(nèi)存可見(jiàn)性角度講,volatile讀相當(dāng)于加鎖,volatile寫(xiě)相當(dāng)于解鎖
synchronized既能保證可見(jiàn)性,又能保證原子性,而volatile只能保證可見(jiàn)性,無(wú)法保證原子性
第五章:課程總結(jié) 5-1 課程總結(jié)

課程總結(jié)

什么是內(nèi)存可見(jiàn)性
Java內(nèi)存模型(JMM)
實(shí)現(xiàn)可見(jiàn)性的方式:synchronized和volatile
    final也可以保證內(nèi)存可見(jiàn)性
synchronized和volatile實(shí)現(xiàn)內(nèi)存可見(jiàn)性的原理
synchronized實(shí)現(xiàn)可見(jiàn)性
    指令重排序
    as-if-serial語(yǔ)義
volatile實(shí)現(xiàn)可見(jiàn)性
    volatile能夠保證可見(jiàn)性
    volatile不能保證原子性
    volatile使用注意事項(xiàng)
synchronized和volatile比較
    volatile比synchronized更輕量級(jí)
    volatile沒(méi)有synchronized使用的廣泛

問(wèn):即使沒(méi)有保證可見(jiàn)性的措施,很多時(shí)候共享變量依然能夠在主內(nèi)存和工作內(nèi)存見(jiàn)得到及時(shí)地更新?

答:一般只有在短時(shí)間內(nèi)高并發(fā)的情況下才會(huì)出現(xiàn)變量得不到及時(shí)更新的情況,因?yàn)镃PU在執(zhí)行時(shí)會(huì)很快的刷新緩存,所以一般情況下很難看到這種情況。

對(duì)64位(long、double)變量的讀寫(xiě)可能不是原子操作

Java內(nèi)存模型允許JVM將沒(méi)有被volatile修飾的64位數(shù)據(jù)類(lèi)型的讀寫(xiě)操作劃分為兩次32位的讀寫(xiě)操作來(lái)進(jìn)行
導(dǎo)致問(wèn)題:有可能會(huì)出現(xiàn)讀取到“半個(gè)變量”的情況
解決辦法:加volatile關(guān)鍵字

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/67326.html

相關(guān)文章

  • 課網(wǎng)_細(xì)說(shuō)線程Thread VS Runnable》學(xué)習(xí)總結(jié)

    摘要:時(shí)間年月日星期六說(shuō)明本文部分內(nèi)容均來(lái)自慕課網(wǎng)。慕課網(wǎng)教學(xué)源碼無(wú)學(xué)習(xí)源碼第一章課前準(zhǔn)備前言課程說(shuō)明比較和這兩種線程創(chuàng)建的方式,需要知道和的基本創(chuàng)建方式。一旦主線程獲取到了用戶(hù)的輸入,這時(shí)候,阻塞就會(huì)解除掉,主線程繼續(xù)運(yùn)行,直到結(jié)束。 時(shí)間:2017年07月08日星期六說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)源碼:無(wú)學(xué)習(xí)源碼:https://g...

    netScorpion 評(píng)論0 收藏0
  • 課網(wǎng)_《Netty入門(mén)WebSocket初體驗(yàn)》學(xué)習(xí)總結(jié)

    時(shí)間:2018年04月11日星期三 說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):https://www.imooc.com 教學(xué)源碼:https://github.com/zccodere/s... 學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:課程介紹 1-1 課程介紹 什么是Netty 高性能、事件驅(qū)動(dòng)、異步非阻塞的IO Java開(kāi)源框架 基于NIO的客戶(hù)...

    Noodles 評(píng)論0 收藏0
  • 課網(wǎng)_Java定時(shí)任務(wù)調(diào)度工具詳解Timer篇》學(xué)習(xí)總結(jié)

    時(shí)間:2017年05月24日星期三說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)示例源碼:無(wú)個(gè)人學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:課程介紹 1-1 課程介紹 什么是定時(shí)任務(wù)調(diào)度 基于給定的時(shí)間點(diǎn),給定的時(shí)間間隔或者給定的執(zhí)行次數(shù)自動(dòng)執(zhí)行的任務(wù) 在Java中的定時(shí)調(diào)度工具 Timer:小弟,能實(shí)現(xiàn)日常60%的定...

    wind5o 評(píng)論0 收藏0
  • 課網(wǎng)_《RxJava與RxAndroid基礎(chǔ)入門(mén)》學(xué)習(xí)總結(jié)

    時(shí)間:2017年10月16日星期一說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)源碼:無(wú)學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:課程簡(jiǎn)介 1-1 課程介紹 本門(mén)課程的主要內(nèi)容 RxJava是什么 RxAndroid是什么 RxJava常用操作符(重點(diǎn)、難點(diǎn)) 怎樣在項(xiàng)目中使用RxJava和RxAndroid 如何學(xué)...

    劉明 評(píng)論0 收藏0
  • 課網(wǎng)_《Hibernate初探對(duì)映射》學(xué)習(xí)總結(jié)

    時(shí)間:2017年07月11日星期二說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)源碼:無(wú)學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:應(yīng)用場(chǎng)景 1-1 多對(duì)多的應(yīng)用場(chǎng)景 案例分析:企業(yè)項(xiàng)目開(kāi)發(fā)過(guò)程中 一個(gè)項(xiàng)目可由多個(gè)員工參與開(kāi)發(fā) 一個(gè)員工可同時(shí)參與開(kāi)發(fā)多個(gè)項(xiàng)目 示意圖 showImg(https://segmentfau...

    caozhijian 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<