Java中的static變量是一種在類級別上定義的變量,而不是在實例級別上定義的。它們與線程有著緊密的關系。
首先,static變量是在內存中分配一次,并在整個應用程序中共享。因此,所有線程都可以訪問和修改這個靜態變量。
然而,因為多個線程可以同時訪問和修改靜態變量,這可能會導致并發問題。例如,如果一個線程正在修改靜態變量,而另一個線程正在訪問它,就可能會出現競態條件和數據不一致的問題。
public class MyThread implements Runnable{ static int counter = 0; public void run(){ for(int i=0; i<100000; i++){ counter++; } } } public class Main{ public static void main(String[] args){ MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); Thread thread1 = new Thread(t1); Thread thread2 = new Thread(t2); thread1.start(); thread2.start(); try{ thread1.join(); thread2.join(); }catch(Exception e){} System.out.println(MyThread.counter); } }
在上面的代碼中,我們定義了一個靜態變量counter,并使用兩個線程同時遞增它。我們使用join()方法等待兩個線程都結束并輸出counter的值。由于競態條件,輸出的結果無法確定,但通常是兩個線程交替遞增。
為了解決這個問題,我們可以使用Java的synchronized關鍵字來保證對靜態變量的訪問是線程安全的。
public class MyThread implements Runnable{ static int counter = 0; static Object lockObject = new Object(); public void run(){ for(int i=0; i<100000; i++){ synchronized(lockObject){ counter++; } } } } public class Main{ public static void main(String[] args){ MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); Thread thread1 = new Thread(t1); Thread thread2 = new Thread(t2); thread1.start(); thread2.start(); try{ thread1.join(); thread2.join(); }catch(Exception e){} System.out.println(MyThread.counter); } }
在上面的代碼中,我們添加了一個鎖對象lockObject,并使用synchronized關鍵字來確保對counter的訪問是原子的。這樣,無論有多少線程訪問counter,我們都能夠保證數據的完整性和一致性。