【相關推薦:】
多個上下文存取SharedArrayBuffer時,如果同時對緩衝區執行操作,就可能出現資源爭用問題。Atomics API 通過強制同一時刻只能對緩衝區執行一個操作,可以讓多個上下文安全地讀寫一個SharedArrayBuffer。
原子操作的本質會排斥作業系統或計算機硬體通常會自動執行的優化(比如指令重新排序)。原子操作也讓並行存取記憶體變得不可能,如果應用不當就可能導致程式執行變慢,為此,Atomics API 的設計初衷是在最少但很穩定的原子行為基礎上,構建複雜的多執行緒JavaScript程式。
Atomics API 提供了一套簡單的方法用於執行就地修改操作。在ECMA規範中,這些方法被定義為AtomicReadModifyWrite操作。在底層,這些方法都會從SharedArrayBuffer中某個位置讀取值,然後執行算術和位元運算,最後再把計算結果寫到相同的位置。這些操作的原子本質意味著上述讀取、修改、寫回操作會按順序執行,不會被其它執行緒中斷。
//建立大小為1的緩衝區let sharedArrayBuffer = new SharedArrayBuffer(1); //基於緩衝建立Unit8Arraylet typedArray = new Unit8Array(sharedArrayBuffer); //所有ArrayBuffer全部初始化為0console.log(typedArray); //Unit8Array[0] //對索引0處的值執行原子加10Atomics.add(typedArray,0,10); //Unit8Array[10] //對索引0處的值執行原子減10Atomics.sub(typedArray,0,10); //Unit8Array[0]
瀏覽器的JavaScript編譯器和CPU架構本身都有許可權重排指令以提升程式執行效率。正常情況下,JavaScript的單執行緒環境是可以隨時進行這種優化的,但是,多執行緒中的指令重排可能導致資源爭用,而且極難排錯。
Atomics API 通過兩種主要方式解決這個問題:
所有原子指令相互之間的順序永遠不會重排。
使用原子讀或原子寫保證所有指令都不會相對原子讀寫重新排序。
除了讀寫緩衝區的值,Atomics.load()和Atomics.store()還可以構建「程式碼圍欄」。JavaScript引擎保證非原子指令可以相對於load()和store()本地重排,但這個重排不會侵犯原子讀寫的邊界。
const sharedArrayBuffer = new SharedArrayBuffer(4); const view = new Unit32Array(sharedArrayBuffer); //執行非原子寫view[0] = 1; //非原子寫可以保證在這個讀操作之前完成,因此這裡一定會讀到1console.log(Atomics.load(view,0)); //1 //執行原子寫Atomics.store(view,0,2); //非原子讀可以保證在原子寫完成後發生,這裡一定會讀到2console.log(view[0]); //2
為了保證連續、不間斷的先讀後寫,Atomics API 提供了兩種方法:exchange()和compareExchange()。Atomics.exchange()執行簡單的交換,以保證其他執行緒不會中斷值得交換。
const sharedArrayBuffer = new SharedArrayBuffer(4); const view = new Unit32Array(sharedArrayBuffer); //在索引0處寫入10Atomics.store(view,0,10); //從索引0處讀取值,然後在索引0處寫入5console.log(Atomics.exchange(view,0,5)); //10 //從索引0處讀取值console.log(Atomics.load(view,0)); //5
在多執行緒程式中,一個執行緒可能只希望在上次讀取某個值之後沒有其他執行緒修改該值得情況下對共用緩衝區執行寫操作。如果這個值沒有被修改,這個執行緒就可以安全地寫入更新後的值:如果這個值被修改了,那麼執行寫操作將會破壞其他執行緒計算的值。對於這種任務,Atomics API提供了compare-Exchange()方法。這個方法只在目標索引處的值與預期值匹配時才會執行寫操作。
如果沒有某種鎖機制,多執行緒程式就無法支援複雜需求。為此,Atomics API提供了模仿Linux Futex(快速使用者空間互斥量,fast user-space mutex)的方法。這些方法本身雖然非常簡單,但可以作為更復雜鎖機制的基本元件。
所有原子Futex操作只能用於Int32Array檢視,而且,只能用在工作執行緒內部。
跨檔案訊息,有時候也稱XDM(cross-document messaging),是一種在不同執行上下文(例如不同工作執行緒或不同源的頁面)間傳遞資訊的能力。
Encoding API主要用於實現字串與定型陣列之間的轉換。
File API仍然以表單中的檔案輸入欄位為基礎,但是增加了直接存取檔案資訊的能力。HTML5在DOM上為檔案輸入元素增加了files集合。當使用者在檔案欄位中選擇一個或多個檔案時,這個files集合中會包含一組File物件,表示被選中的檔案,每個File物件都有一些唯讀屬性。
FileReader型別表示一種非同步檔案讀取機制,可以把FileReader想象成類似於XMLHttpRequest,只不過用於從檔案系統讀取檔案,而不是從伺服器讀取資料。FileReader型別提供了幾個讀取檔案資料的方法。
readAsText(file,encoding);//從檔案中讀取純文字內容並儲存在result屬性中
readAsDataURL(file);//讀取檔案並將內容的資料URI儲存在result屬性中
readAsBinaryString(file);//讀取檔案並將每個字元的二進位制資料儲存在result屬性中
readAsArrayBuffer(file);//讀取檔案並將檔案內容以ArrayBuffer形式儲存在result屬性中
FileReader型別的同步版本。
某些情況下,可能需要讀取部分檔案而不是整個檔案,為此,File物件提供了一個名為slice()的方法。slice()方法接收兩個引數:起始位元組和堯都區的位元組數。這個方法返回一個Blob的範例,而Blob實際上是File的超類。
blob表示二進位制大物件,是JavaScript對不可修改二進位制資料的封裝型別。包含字串的陣列、ArrayBuffers、ArrayBufferViews,甚至其他Blob都可以用來建立blob。Blob建構函式可以接收一個options引數,並在其中指定MIME型別。
Streams API 是為了解決一個簡單但又很基礎的問題而生的:Web應用如何消費有序的小資訊塊而不是大塊資訊?這種能力主要有兩種應用場景。
Streams API定義了三種流:
可讀流:可以通過某個公共介面讀取資料塊的流。資料在內部從底層源進入流,然後由消費者consumer進行處理。
可寫流:可以通過某個公共介面寫入資料塊的流。生產者(consumer)將資料寫入流,資料在內部傳入底層資料槽(sink)。
轉換流:由兩種流組成,可寫流用於接收資料,可讀流用於輸出資料。這兩個流質檢是轉換程式(transformer),可以根據需要檢查和修改流內容。
Web Cryptography API描述了一套密碼學工具,規範了JavaScript如何以安全和符合慣例的方式實現加密。這些工具包括生成、使用和應用加密祕鑰對,加密和解密資訊,以及可靠地生成亂數。
在需要生成亂數時,很多人會使用Math.random()
。這個方法在瀏覽器中是以偽亂數生成器(PRNG,PseudoRandom Number Generator)方式實現的。所謂的偽指的是生成值的過程不是真的隨機。PRNG生成的值只是模擬了隨機的特性。瀏覽器的PRNG並未使用真正的隨機源,只是對一個內部狀態應用了固定的演演算法。每次呼叫Math.random()
,這個內部狀態都會被一個演演算法修改,而結果會被轉換為一個新的亂數。例如,V8引擎使用了一個名為xorshift128+
的演演算法來執行這種修改。
由於演演算法本身是固定的,其輸入只是之前的狀態,因此亂數順序也是確定的。xorshift128+
使用128位元內部狀態,而演演算法的設計讓任何初始狀態在重複自身之前都會產生2128-1個偽隨機值。這種迴圈被稱為置換回圈,而這個迴圈的長度被稱為一個週期。很明顯,如果攻擊者知道PRNG的內部狀態,就可以預測後續生成的偽隨機值。如果開發者無意中使用了PRNG生成了私有金鑰用於加密,則攻擊者就可以利用PRNG的這個特性算出私有金鑰。
偽亂數生成器主要用於快速計算出看起來隨機的數,不過並不適合用於加密演演算法,為解決這個問題,密碼學安全偽亂數生成器(CSPRNG,Cryptographically Secure PseudoRandom Number Generator),額外增加了一個熵作為輸入,例如測試硬體時間或其它無法預計行為的系統特性,雖然速度上不及PRNG,但是生成的值更難預測了,就可以用於加密。
Web Cryptography API引入了CSPRNG,這個CSPRNG可以通過crypto.getRandomValues()
在全域性Crypto
物件上存取。與Math.random()
返回一個0到1之間的浮點數不同,getRandomValues()
會把隨機值寫入作為引數傳給它的定型陣列。定型陣列的類不重要,因為底層緩衝區會被隨機的二進位制位填充。
【相關推薦:、】
以上就是帶你學習JavaScript中的File API、Streams API和Web Cryptography API的詳細內容,更多請關注TW511.COM其它相關文章!