關於JAVA中的static方法、並發問題以及JAVA運行時記憶體模型

來源:互聯網
上載者:User

標籤:image   求和   調用   記憶體回收行程   對象   package   線程並發   sum   自己的   

一、前言

最近在工作上用到了一個靜態方法,跟同事交流的時候,被一個問題給問倒了,只怪基礎不紮實...

問題大致是這樣的,“在多線程環境下,靜態方法中的局部變數會不會被其它線程給汙染掉?”;

我當時的想法:方法中的局部變數在啟動並執行時候,是存在JAVA棧中的,方法運行結束,局部變數也就都彈光了,理論上單線程的話是不會有問題的,我之所以不知道,是因為不清楚在JAVA記憶體模型中,一個線程對應一個棧,還是多個線程共用一個棧...

其實如果知道每個線程都有一個自己的JAVA棧的話,問題也就很清楚了,不會被其它線程給汙染掉;

當然,問題並不能止於此,這個問題已經暴露出自己對這方面比較薄弱,因此打算對JAVA記憶體模型和多線程並發問題做個小小總結;

 二、JAVA中的記憶體模型

程式啟動並執行時候,記憶體主要由以下部分組成:

  1. :所有線程共用一個堆;存放的都是new 出來的對象;由記憶體回收行程回收;
  2. 方法區:所有線程共用一個方法區;裡面存放的內容有點雜,可以認為是除堆和棧中的其它東西(如類資訊,靜態變數,常量,代碼等);Java虛擬機器規範規定可以不對方法區進行記憶體回收,當並不是不回收,主要看具體虛擬機器的實現,比如可以回收一些廢棄常量和無用的類;
  3. 程式計數器:也叫PC,存放下一條指令所在單元的地址的地方;
  4. JAVA棧:每個線程都有一個自己的JAVA棧;存放的一般是方法的局部變數,方法出口資訊等;方法調用過程中,自動壓棧出棧;ps:棧空間大小是有限制的;
  5. 本地方法棧:與JAVA棧類似,區別是使用的對象不一樣,本地方法棧是給Native方法使用的,JAVA棧是給JAVA方式使用的;

附一張圖片,會對java虛擬機器有個整體的認識;

三、多線程訪問共用記憶體情況

當多個線程執行同一個方法的時候,

什麼時候可能會出現異常結果:

多個線程共用一塊記憶體地區,在不加任何保護情況下,對其操作;

什麼時候可能會得到正確的結果:

不使用共用記憶體,每個線程記憶體空間相互獨立;

多線程共用一塊記憶體地區,但是對這塊共用地區加鎖訪問;

 四、執行個體說明

情況一(多個線程共用一塊記憶體地區,在不加任何保護情況下,對其操作):

寫一個含靜態方法的類,求和,方法內用了一個靜態全域s(多個線程可以同時訪問):

package com.pichen.java.static_;public class StaticTest {    private static int s = 0;    public static int sum(int n){        s = 0;        for(int i = 0; i <= n; i++){            s += i;                        try {                Thread.sleep(1);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        return s;    }}

寫一個Thread,調用上面的靜態方法:

package com.pichen.java.static_;public class ThreadCount implements Runnable{    @Override    public void run() {        while(true){            System.out.println(Thread.currentThread().getName() +":" +StaticTest.sum(100));            try {                Thread.sleep(10);            } catch (InterruptedException e) {                e.printStackTrace();            }        }            }}

寫個Main函數,起三個線程,觀察運行結果,基本都是錯誤的:

package com.pichen.java.static_;public class Main {    public static void main(String[] args) {        ThreadCount t1 = new ThreadCount();        new Thread(t1).start();                ThreadCount t2 = new ThreadCount();        new Thread(t2).start();                ThreadCount t3 = new ThreadCount();        new Thread(t3).start();    }}

運行結果不符合預期:

Thread-0:13968Thread-1:13968Thread-2:13968Thread-0:13033Thread-1:13033Thread-2:13033Thread-1:14725Thread-0:14725

原因:多個線程同時對靜態全域變數s進行操作導致;

ps:這裡的例子是靜態全域變數s,其實有很多種情況會引起結果異常問題,如在main方法中new出了一個對象,new出來的對象是存放在堆中的,多個線程共用,此時如果多線程同時操作該對象的話,也是有可能產生錯誤結果;

情況二(不使用共用記憶體,每個線程記憶體空間相互獨立):

修改靜態sum方法,使用局部變數s,如下:

package com.pichen.java.static_;public class StaticTest {    private static int s = 0;    public static int sum(int n){        int s = 0;        for(int i = 0; i <= n; i++){            s += i;                        try {                Thread.sleep(1);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        return s;    }}

運行程式,結果正確:

Thread-1:5050Thread-0:5050Thread-2:5050Thread-0:5050Thread-2:5050Thread-1:5050Thread-0:5050

情況三(多線程共用一塊記憶體地區,但是對這塊共用地區加鎖訪問):
package com.pichen.java.static_;public class StaticTest {    private static int s = 0;    public synchronized static int sum(int n){        s = 0;        for(int i = 0; i <= n; i++){            s += i;                        try {                Thread.sleep(1);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        return s;    }

運行程式,結果正確:

Thread-1:5050Thread-0:5050Thread-2:5050Thread-0:5050Thread-2:5050Thread-1:5050Thread-0:5050

轉載地址 :http://www.cnblogs.com/chenpi/p/5159558.html 感謝原文作者

關於JAVA中的static方法、並發問題以及JAVA運行時記憶體模型

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.