java中多個用戶調用同一個方法程序的處理過程以及併發問題

        java中多個用戶在訪問同一段代碼的時候,後臺會爲每一個請求分配一個單獨的線程來處理,線程之間是相互獨立的,互不干擾,當然也可以相互通信。併發問題只有在多個線程之間可能修改同一資源的時候纔會出現,解決併發問題可以通過加鎖來解決。好比說多個用戶同時登陸一個系統時,都需要用到登陸的相關代碼,是不會發生什麼衝突的。好比說對一個財務系統,兩個人同時對總錢數進行操作,一個加10塊一個減100塊,注意這兩個操作是同時進行的,那系統就不知道是加還是減了,這是併發問題。加鎖解決就是,在一個請求開始對這條記錄操作時,其它的請求就不能對它操作了,直到現在正在進行的操作完成。

        多線程併發的處理,這裏指的是服務器端,也就是 Java 的處理,與頁面無關。

       首先,當多個請求同時到達服務器時,服務器會分配線程來執行每個請求(如果請求數量太多,能用的線程有限,則會進行排隊)。所以請求和請求之間首先是一個線程隔離的環境。

       每個線程都會按照同樣的順序執行同樣的代碼(這裏簡單的不考慮分支),在執行代碼的過程中,線程會訪問和操作各種各樣的對象和變量。所以這裏就有一個問題:我怎麼知道多個線程會不會訪問到同一個對象,或者同一個變量呢?如果這樣的事情發生了,可能會產生什麼後果呢?

        在詳細解釋這個問題之前,首先需要明確一個簡單的原則:任何對象都可以被任意多個線程訪問,這是代碼的自由性決定的。但更重要的是,我們可以讓對象主動掌控線程對自己的訪問。

     最簡單的控制方式就是 synchronized,意即同時只允許一個線程訪問,其它線程必須先等待。當 synchronized 用在方法上時,表示同一時間只允許一個線程執行這個方法。

       那麼是否意味着服務器上的所有方法都必須是synchronized的呢?不是。當一個方法執行時,所有的變量和參數都會保存在一個叫做堆棧的內存空間,這個內存空間是線程獨享的,所以線程之間不會相互衝突。例如:

public void hello(String name) {

String greetings = "Hello, " + name;
System.out.println(greetings);

}
        當多個線程執行 hello() 方法時,每個線程都會在自己的堆棧中存放 name 參數和 greetings 變量。其中 greetings 變量是在方法內定義的,一個線程中的 greetings 變量與另一個線程中的 greetings 變量將是完全隔離的,不會相互影響。

        堆棧是線程獨享的,但是放入堆棧的內容則未必。像上面的例子,greetings 變量是線程自己創建的,所以其它線程訪問不到,但 name 參數則未必,有可能多個線程在執行這個方法時,收到的 name 參數是同一個對象。這時候如果方法裏面要修改這個對象,那就要小心了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章