主頁 > 移動端開發 > 并發編程之JMM&Volatile底層原理剖析

并發編程之JMM&Volatile底層原理剖析

2020-10-16 15:01:53 移動端開發

初步認識 Volatile

一段代碼引發的思考,下面這段 代碼演示了使用valatile和沒有使用volatile關鍵字對于變數更新的影響

public class App {
    public volatile static boolean stop = false;
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()->{
            int i = 0;
            while(!stop){
                i ++;
            }
        });
        t1.start();
        System.out.println("begin");
        Thread.sleep(1000);
        stop = true;
    }
}

volatile的作用

可以使得在多處理器環境下保證共享變數的可見性,什么是可見性?

在單執行緒的環境下,如果向一個變數先寫入一個值,然后再沒有寫干涉的情況下讀取這個變數,這個時候讀取到的這個變數值應該是之前寫入的值,這本來是一個很正常的事情,但是在多執行緒環境下,讀和寫發生在不同執行緒中的時候可能會出現:讀執行緒不能即使讀取到其他執行緒寫入的最新值,這就是所謂的可見性,為了實作多執行緒寫入的記憶體可見性,必須使用一些機制,而volatile就是這樣一種機制

volatile 關鍵字是如何保證可見性的?

在運行main函式之前,加入虛擬機引數

-server -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:CompileCommand=compileonly,*XXX.function(xxx替換成實際運行的類,function替換方法名)

然后在輸出的結果中,查找下 lock 指令, 會發現,在修改帶有 volatile 修飾的成員變數時,會多一個lock 指令, lock是一種控制指令, 在多處理器環境下, lock 匯編指令可以基于總線鎖或者快取鎖的機制來達到可見性的一個效果

為了更好的理解可見性的本質, 我們需要從硬體層面進行梳理

從硬體層面了解可見性的本質

一臺計算機最核心的組件時CPU,記憶體以及I/O設備不斷迭代升級來提升計算機處理能力之外,還有一個非常核心的矛盾點,就是這三者在處理速度的差異,CPU 的計算速度是非常快的,記憶體次之、最后是 IO 設備比如磁盤,而在絕大部分的程式中,一定會存在記憶體訪問,有些可能還會存在 I/O 設備的訪問,

為了提升計算性能, CPU 從單核升級到了多核甚至用到了超執行緒技術最大化提高 CPU 的處理性能,但是僅僅提升CPU 性能還不夠,如果后面兩者的處理性能沒有跟上,意味著整體的計算效率取決于最慢的設備, 為了平衡三者的速度差異,最大化的利用 CPU 提升性能,從硬體、作業系統、編譯器等方面都做出了很多的優化,

  1. CPU 增加了高速快取
  2. 作業系統增加了行程、執行緒,通過 CPU 的時間片切換最大化的提升 CPU 的使用率
  3. 編譯器的指令優化,更合理的去利用好 CPU 的高速快取

然而每一種優化,都會帶來相應的問題,而這些問題也是導致執行緒安全性問題的根源, 為了了解前面提到的可見性問題的本質,我們有必要去了解這些優化的程序

CPU快取架構

CPU快取即高速緩沖存盤器,是位于CPU與主記憶體間的一種容量較小但速度很高的存盤器,由于CPU的速度遠高于主記憶體,CPU直接從記憶體中存取資料要等待一定時間周期,Cache中保存著CPU剛用過或回圈使用的一部分資料,當CPU再次使用該部分資料時可從Cache中直接呼叫,減少CPU的等待時間,提高了系統的效率

通過高速快取的存盤互動很好的解決了處理器與記憶體的速度矛盾,但是也為計算機系統帶來了更高的復雜度,因為它引入了一個新的問題,快取一致性

什么叫快取一致性呢?

首先,有了高速快取的存在以后, 每個 CPU 的處理程序是,先將計算需要用到的資料快取在 CPU 高速快取中,在 CPU進行計算時,直接從高速快取中讀取資料并且在計算完成,之后寫入到快取中, 在整個運算程序完成后,再把快取中的資料同步到主記憶體

由于在多 CPU 種,每個執行緒可能會運行在不同的 CPU 內,并且每個執行緒擁有自己的高速快取, 同一份資料可能會被快取到多個 CPU 中,如果在不同 CPU 中運行的不同執行緒看到同一份記憶體的快取值不一樣就會存在快取不一致的問題,

為了解決快取不一致的問題,在 CPU 層面做了很多事情,

主要提供了兩種解決辦法l

1. 總線鎖

2. 快取鎖

JMM&volatile.jpg

總線鎖,簡單來說就是,在多 cpu 下,當其中一個處理器要對共享記憶體進行操作的時候,在總線上發出一個 LOCK#信號,這個信號使得其他處理器無法通過總線來訪問到共享記憶體中的資料, 總線鎖定把 CPU 和記憶體之間的通信鎖住了,這使得鎖定期間,其他處理器不能操作其他記憶體地址的資料,所以總線鎖定的開銷比較大, 這種機制顯然是不合適的

如何優化呢? 最好的方法就是控制鎖的保護粒度,我們只需要保證對于被多個 CPU 快取的同一份資料是一致的就行, 所以引入了快取鎖, 它核心機制是基于快取一致性協議來實作的

快取一致性協議

為了達到資料訪問的一致,需要各個處理器在訪問快取時遵循一些協議,在讀寫時根據協議來操作,常見的協議有MSI, MESI, MOSI 等, 最常見的就是 MESI 協議

MESI 表示快取行的四種狀態,分別是:

  1. M(Modify) 表示共享資料只快取在當前 CPU 快取中,并且是被修改狀態,也就是快取的資料和主記憶體中的資料不一致

2.E(Exclusive) 表示快取的獨占狀態,資料只快取在當前CPU 快取中,并且沒有被修改

3.S(Shared) 表示資料可能被多個 CPU 快取,并且各個快取中的資料和主記憶體資料一致

4.I(Invalid) 表示快取已經失效

在 MESI 協議中,每個快取的快取控制器不僅知道自己的讀寫操作,而且也監聽(snoop)其它 Cache 的讀寫操作

關鍵 對于 MESI 協議, 從 CPU 讀寫角度來說會遵循以下原則:CPU 讀請求:快取處于 M、 E、 S 狀態都可以被讀取, I 狀態 CPU 只能從主存中讀取資料CPU 寫請求:快取處于 M、 E 狀態才可以被寫,對于 S 狀態的寫,需要將其他 CPU 中快取行置為無效才可寫使用總線鎖和快取鎖機制之后, CPU 對于記憶體的操作大概可以抽象成下面這樣的結構,從而達到快取一致性效果

MESI 優化帶來的可見性問題

MESI 協議雖然可以實作快取的一致性,但是也會存在一些問題,

就是各個 CPU 快取行的狀態是通過訊息傳遞來進行的, 如果 CPU0 要對一個在快取中共享的變數進行寫入,首先需要發送一個失效的訊息給到其他快取該資料的 CPU(Invalid),并且要等到他們的確認回執, CPU0 在這段時間內都會處于阻塞狀態, 為了避免阻塞帶來的資源浪費, 在 cpu 中引入了 Store Bufferes

CPU0 只需要在寫入共享資料時,直接把資料寫入到 storebufferes 中, 同時發送 invalidate 訊息,然后繼續去處理其他指令,當收到其他所有 CPU 發送了 invalidate acknowledge 訊息時, 再將 store bufferes 中的資料資料存盤至 cache line中,最后再從快取行同步到主記憶體,

但是這種優化存在兩個問題

1. 資料什么時候提交是不確定的,因為需要等待其他 cpu給回復才會進行資料同步,這里其實是一個異步操作

2. 引入了 storebufferes 后,處理器會先嘗試從 storebuffer中讀取值,如果 storebuffer 中有資料,則直接從storebuffer 中讀取,否則就再從快取行中讀取

看個例子:

//cpu已經快取了Flag
//M(Modify)  E(Exclusive) S(Shared)  I(Invalid) 狀態
value = 3 //(S)
void cpu0(){
    value = 10; //( M) ->[ storebufferes ->通知其他cpu快取行失效(i)] 
    Flag = true;//(E)
}
void cpu1(){
   if(Flag){//true
       assert value ==10;//flase
   }
}

cpu0和cpu1分別在倆個獨立cpu上執行,假如cpu0快取行中快取了isFlag這個共享變數且狀態(E),而Vlaue可能是(S)狀態,

這時候,CPU0在執行的時候,會先把value=10寫入到storebuffer中,并且通知其他快取了value的cpu.,在等待其他CPU通知結果的時候,cpu0會先執行isFlag=true的指令,

而因為當前cpu0快取了isFlag并且是(E)狀態,所以可以直接修改isFlag=true,但是value值還不等于10.

這種情況我們可以認為是CPU的亂序執行,也可以認為是重排序,這種重排序會帶來可見性問題,

從硬體層面很難去知道軟體層面上的這種前后依賴關系,沒有辦法通過某種手段自動去解決,所以在 CPU 層面提供了 memory barrier(記憶體屏障)的指令,從硬體層面來看這個 memroy barrier 就是 CPU flushstore bufferes 中的指令,軟體層面可以決定在適當的地方來插入記憶體屏障,

總的來說,記憶體屏障的作用可以通過防止 CPU 對記憶體的亂序訪問來保證共享資料在多執行緒并行執行下的可見性但是這個屏障怎么來加呢?回到最開始我們講 volatile 關鍵字的代碼,這個關鍵字會生成一個 Lock 的匯編指令,這個指令其實就相當于實作了一種記憶體屏障.

這個時候問題又來了, 記憶體屏障、重排序這些東西好像是和平臺以及硬體架構有關系的, 作為 Java 語言的特性,一次撰寫多處運行, 我們不應該考慮平臺相關的問題,并且這些所謂的記憶體屏障也不應該讓程式員來關心,

JMM

什么是JMM

JMM 全稱是 Java Memory Model. 什么是 JMM 呢?

JMM模型跟CPU快取模型結構類似,是基于CPU快取模型建立起來的,JMM模型是標準化的,屏蔽掉了底層不同計算機的區別,對于硬體記憶體來說只有暫存器、快取記憶體、主記憶體的概念,并沒有作業記憶體(執行緒私有資料區域)和主記憶體(堆記憶體)之分,因為JMM只是一種抽象的概念,是一組規則,并不實際存在,不管是作業記憶體的資料還是主記憶體的資料,對于計算機硬體來說都會存盤在計算機主記憶體中,當然也有可能存盤到CPU快取或者暫存器中,

通過這些規則來規范對記憶體的讀寫操作從而保證指令的正確性,它解決了 CPU 多級快取、處理器優化、指令重排序導致的記憶體訪問問題,保證了并發場景下的可見性

需要注意的是, JMM 并沒有限制執行引擎使用處理器的暫存器或者高速快取來提升指令執行速度,也沒有限制編譯器對指令進行重排序,也就是說在 JMM 中,也會存在快取一致性問題和指令重排序問題,只是 JMM 把底層的問題抽象到 JVM 層面,再基于 CPU 層面提供的記憶體屏障指令,以及限制編譯器的重排序來解決并發問題

java 記憶體模型底層實作可以簡單的認為: 通過記憶體屏障(memory barrier)禁止重排序,即時編譯器根據具體的底層體系架構,將這些記憶體屏障替換成具體的 CPU 指令,對于編譯器而言,記憶體屏障將限制它所能做的重排序優化,而對于處理器而言,記憶體屏障將會導致快取的重繪操作,比如,對于 volatile,編譯器將在 volatile 欄位的讀寫操作前后各插入一些記憶體屏障

簡單來說, JMM 提供了一些禁用快取以及進制重排序的方法,來解決可見性和有序性問題, 這些方法大家都很熟悉:volatile、 synchronized、 final;以及HappenBefore規則

重排序

注意:X86處理器不會對讀-讀、讀-寫和寫-寫操作做重排序, 會省略掉這3種操作型別對應的記憶體屏障,僅會對寫-讀操作做重排序,所以volatile寫-讀操作只需要在volatile寫后插入StoreLoad屏障

為了提高程式的執行性能,編譯器和處理器都會對指令做重排序,其中處理器的重排序在前面已經分析過了, 所謂的重排序其實就是指執行的指令順序,編譯器的重排序指的是程式撰寫的指令在編譯之后,指令可能會產生重排序來優化程式的執行性能

從源代碼到最終執行的指令,可能會經過三種重排序

2 和 3 屬于處理器重排序,這些重排序可能會導致可見性問題,

編譯器的重排序, JMM 提供了禁止特定型別的編譯器重排序

處理器重排序, JMM 會要求編譯器生成指令時,會插入記憶體屏障來禁止處理器重排序

記憶體屏障

硬體層提供了一系列的記憶體屏障 memory barrier / memory fence(Intel的提法)來提供一致性的能力,拿X86平臺來說,有幾種主要的記憶體屏障:

  1. lfence,是一種Load Barrier 讀屏障
  2. sfence, 是一種Store Barrier 寫屏障
  3. mfence, 是一種全能型的屏障,具備lfence和sfence的能力
  4. Lock前綴,Lock不是一種記憶體屏障,但是它能完成類似記憶體屏障的功能,Lock會對CPU總線和高速快取加鎖,可以理解為CPU指令級的一種鎖,它后面可以跟ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, and XCHG等指令,

記憶體屏障有兩個能力:

  1. 阻止屏障兩邊的指令重排序
  2. 重繪處理器快取/沖刷處理器快取

對Load Barrier來說,在讀指令前插入讀屏障,可以讓高速快取中的資料失效,重新從主記憶體加載資料

對Store Barrier來說,在寫指令之后插入寫屏障,能讓寫入快取的最新資料寫回到主記憶體

Lock前綴實作了類似的能力,它先對總線和快取加鎖,然后執行后面的指令,最后釋放鎖后會把高速快取中的資料重繪回主記憶體,在Lock鎖住總線的時候,其他CPU的讀寫請求都會被阻塞,直到鎖釋放,

JMM 層面的記憶體屏障

為了保證記憶體可見性, Java 編譯器在生成指令序列的適當位置會插入記憶體屏障來禁止特定型別的處理器的重排序,在 JMM 中把記憶體屏障分為四類

  1. load1 loadload load2 -> load1 早于load2 讀讀屏障
  2. strore1 strorestore store2 -> 寫寫屏障
  3. load loadstore store ->讀寫屏障
  4. store storeload load ->全屏障

我們通過 javap -v xxx.class命令查看匯編指令會發現,假如了volatile關鍵字后有這么一條指令

flags: ACC_PUBLIC, ACC_STATIC, ACC_VOLATILE

煩是volatile關鍵字 最后一定會執行 stroeload();

不同平臺下實作的檔案

如果存在重排序情況下, JMM提供了倆級別記憶體屏障(cpu,語言級別)

lock匯編指令:cpu級別記憶體屏障,鎖住快取行

volatile :語言級別記憶體屏障,禁止編譯器對代碼優化(重排序)

as-if-serial

as-if-serial語意的意思是:不管怎么重排序(編譯器和處理器為了提高并行度),(單執行緒)程式的執行結果不能被改變,編譯器、runtime和處理器都必須遵守as-if-serial語意,

為了遵守as-if-serial語意,編譯器和處理器不會對存在資料依賴關系的操作做重排序,因為這種重排序會改變執行結果,但是,如果操作之間不存在資料依賴關系,這些操作就可能被編譯器和處理器重排序,

a =1;
b=2;
c = a*b;

A和C之間存在資料依賴關系,同時B和C之間也存在資料依賴關系,因此在最終執行的指令序列中,C不能被重排序到A和B的前面(C排到A和B的前面,程式的結果將會被改變),但A和B之間沒有資料依賴關系,編譯器和處理器可以重排序A和B之間的執行順序

happens-before

在JMM中,如果一個操作執行的結果需要對另一個操作可見,那么這兩個操作之間必須存在happens-before關系,

  1. 程式次序規則:一個執行緒內,按照代碼順序,書寫在前面的操作先行發生于書寫在后面的操作;
  2. 鎖定規則:一個unLock操作先行發生于后面對同一個鎖的lock操作;
  3. volatile變數規則:對一個變數的寫操作先行發生于后面對這個變數的讀操作;
  4. 傳遞規則:如果操作A先行發生于操作B,而操作B又先行發生于操作C,則可以得出操作A先行發生于操作C;
  5. 執行緒啟動規則:Thread物件的start()方法先行發生于此執行緒的每個一個動作;
  6. 執行緒中斷規則:對執行緒interrupt()方法的呼叫先行發生于被中斷執行緒的代碼檢測到中斷事件的發生;
  7. 執行緒終結規則:執行緒中所有的操作都先行發生于執行緒的終止檢測,我們可以通過Thread.join()方法結束、Thread.isAlive()的回傳值手段檢測到執行緒已經終止執行;
  8. 物件終結規則:一個物件的初始化完成先行發生于他的finalize()方法的開始;

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/174249.html

標籤:其他

上一篇:Java之父都需要的一本能夠更深入地了解Java編程語言的書

下一篇:虎牙、斗魚正式達成合并協議;?中國廣電正式成立,或催生5G發展新格局;Linux 5.9 釋出|極客頭條

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more