日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java并发之初识

發(fā)布時間:2023/12/4 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java并发之初识 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一:并發(fā)編程的難點

1:原子性問題

  • 操作系統(tǒng)做任務切換,可以發(fā)生在任何一條CPU指令執(zhí)行完成后;
  • CPU能保證的原子操作是指令級別的,而不是高級語言的操作符;
    n++不是原子操作的,而是3條指令

2:可見性問題

  • 可見性是指一個線程對一個變量進行修改,另外一個線程可以看的到
  • 可見性問題是由CPU的緩存導致的,多核CPU均有各自的緩存,這些緩存要與內存進行同步。(其實就是多線程環(huán)境下,一個線程對一個變量的改變了,而另一個線程沒看到,那么的話還是按照原來的變量的值進行計算的話,那么就會出錯)。

3:有序性問題

  • 在執(zhí)行程序時,為了提高性能,編譯器和處理器常常會對指令做重排序;
  • 重排序不會影響單線程的執(zhí)行結果,但是在并發(fā)情況下,可能會出現(xiàn)詭異的BUG。

二:并發(fā)編程

1:并發(fā)編程的目標

解決多核多線程下,造成的 緩存不一致問題,指令重排問題,處理器優(yōu)化問題

  • 在cpu和主存之間添加緩存,在多線程下會存在緩存一致性問題(可見性問題)
  • 處理器內部為了使運算單元盡可能的被充分利用,處理器可能會對輸入的代碼進行亂序處理。這就是處理器優(yōu)化。(原子性問題)
  • 很多編程語言的編譯器也會有類似的優(yōu)化,比如Java虛擬機的即時編譯器(JIT)也會做指令重排。(指令重排問題)

2:并發(fā)編程的內存模型

  • 為了保證共享內存的正確性(可見性、有序性、原子性),內存模型定義了共享內存系統(tǒng)中多線程程序讀寫操作行為的規(guī)范。
  • 通過這些規(guī)則來規(guī)范對內存的讀寫操作,從而保證指令執(zhí)行的正確性。它與處理器有關、與緩存有關、與并發(fā)有關、與編譯器也有關。他解決了CPU多級緩存、處理器優(yōu)化、指令重排等導致的內存訪問問題,保證了并發(fā)場景下的一致性、原子性和有序性。

3:這個內存模型是什么

  • JMM是Java Memory Model的縮寫,Java線程之間的通信由JMM控制,即JMM決定一個線程對共享變量的寫入何時對另一個線程可見。
  • JMM定義了線程和主內存之間的抽象關系,通過控制主內存與每個本地內存(抽象概念)之間的交互,JMM為Java程序員提供了內存可見性的保證。
  • JMM是一種規(guī)范,目的是解決由于多線程通過共享內存進行通信時,存在的本地內存數(shù)據不一致、編譯器會對代碼指令重排序、處理器會對代碼亂序執(zhí)行等帶來的問題。

4:源代碼和指令間的重排序

為了提高性能,編譯器和處理器常常會對指令做重排序。重排序有3種類型,其中后2種都是處理器重排序。這些重排序可能會導致多線程程序出現(xiàn)內存可見性問題。

  • 1.編譯器優(yōu)化重排序:編譯器在不改變單線程程序語義的前提下,可以重新安排語句的執(zhí)行順序。
  • 2.指令級并行重排序:現(xiàn)代處理器采用了指令級并行技術來將多條指令重疊執(zhí)行,如果不存在數(shù)據依賴性,處理器可以改變語句對應機器指令的執(zhí)行順序。
  • 3.內存系統(tǒng)的重排序:由于處理器使用緩存和讀/寫緩沖區(qū),這使得加載和存儲操作看上去可能是在亂序執(zhí)行。

5:解決CPU帶來的重排序

  • CPU內存屏障:
    • 1.LoadLoad:禁止讀和讀的重排序;
    • 2.StoreStore:禁止寫和寫的重排序,
    • 3.LoadStore:禁止讀和寫的重排序,
    • 4.StoreLoad:禁止寫和讀的重排序。
  • Java內存屏障:
public final class Unsafef{ public native void loadFence();//LoadLoad LoadStore public native void storeFence();//StoreStore LoadStore public native void fullFence();//loadFence()+storeFence()+StoreLoad }

6:解決編譯器帶來的重排序

(1):如何解決

JMM使用nappens-before規(guī)則來闡述操作之間的內存可見性,以及什么時候不能重排序。在JMM中如果一個操作執(zhí)行的結果需要對另一個操作可見,那么這兩個操作之間必須要存在nappens-.before:關系。換個角度來說,如果A happens-before B,則意味著A的執(zhí)行結果必須對B可見,也就是保證跨線程的內存可見性。其中,前4條規(guī)則與程序員密切相關。

  • 1.程序順序規(guī)則:一個線程中的每個操作,happens-before于(對…可見)該線程中的任意后續(xù)操作,
  • 2.volatile?變量規(guī)則:對一個volatile域的寫,happens-before于任意后續(xù)對這個volatile域的讀,
  • 3.synchronized規(guī)則:對一個鎖的解鎖,happens-before于隨后對這個鎖的加鎖,
  • 4.傳遞性:若A happens-.before B,且B happens-before C,則A happens-before C,
  • 5.start()規(guī)則:若線程A執(zhí)行Thread.start(0,則線程A的start()操作nappens-before于線程B中的任意操作,
  • 6.join規(guī)則:若線程A執(zhí)行ThreadB.join0并成功返回,那么線程B中的任意操作happens-.before于線程A從ThreadB.join0的成功返回。

(2):關鍵字vlatile

  • 4.1 volatile的基本特性
    • 可見性:對一個volatile變量的讀,總是能看到對這個volatile變量最后的寫入:
    • 原子性:對任意單個volatile變量的讀/寫具有原子性,但類似volatile++這種復合操作不具有原子性。
  • 4.2 volatilet的內存語義
    • 寫內存語義:當寫一個volatile變量時,JMM會把該線程本地內存中的共享變量的值刷新到主內存
    • 讀內存語義:當讀一個volatile變量時,JMM會把該線程本地內存置為無效,使其從主內存中讀取共享變量。

總結

以上是生活随笔為你收集整理的java并发之初识的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。