多執行緒(3)-多執行緒訪問共享物件和資料的方式
阿新 • • 發佈:2018-12-20
在多執行緒(2)-ThreadLocal,我們討論了執行緒範圍內的資料共享,本篇文章我們討論執行緒之間即多執行緒訪問共享物件和資料的方式
一:Java5之前給共享資料加上鎖synchronized,上程式碼
public class MultiThreadShareData { public static void main(String[] args) { ShareData1 data2 = new ShareData1(); new Thread(new MyRunnable1(data2)).start(); new Thread(new MyRunnable2(data2)).start(); /*final ShareData1 data1 = new ShareData1(); new Thread(() -> data1.decrement()).start();//lambda表示式 new Thread(new Runnable(){ @Override public void run() { data1.increment(); } }).start();*/ } } class MyRunnable1 implements Runnable{ private ShareData1 data1; public MyRunnable1(ShareData1 data1){ this.data1 = data1; } public void run() { data1.decrement(); } } class MyRunnable2 implements Runnable{ private ShareData1 data1; public MyRunnable2(ShareData1 data1){ this.data1 = data1; } public void run() { data1.increment(); } } class ShareData1 /*implements Runnable*/{ private int j = 0; public synchronized void increment(){ j++; System.out.println(j); } public synchronized void decrement(){ j--; System.out.println(j); } }
以上實現了兩種方式,開啟註釋便是第二種方式。總之,要同步互斥的程式碼最好放到一個類的幾個獨立的方法中,實現就比較簡單。且共享資料的作用範圍(生命週期)比呼叫的具體方法的生命週期大。
這是Java5之前就有的,而在Java5之後利用concurrent包,能完成很多不同的操作。此文中可以直接利用concurrent的atomic類,
二Atomic類
參照Java1.5的開發手冊
以AtomicInteger為例,解決多執行緒訪問整數的問題,很多API,
在增減時,最終會用到CAS,
關於compareAndSet,就是樂觀鎖嘛,比較後賦值,不同的時候才賦值。這是cas+自旋的操作,直到不同的時候才賦值。此處為Java1.8的原始碼;
類似的還有AtomicIntegerArray,AtomicIntegerFieldUpdate,分別是運算元組裡的整數和類裡的整數屬性。