近在讀《深入理解並行編程》,是C的,前面的200頁感覺是通用的思想,前面提到有一個計數器的問題,於是就自己想着用java來實現下.
中間有遇到問題:
1.假設只有兩個線程,一讀一寫,是否需要給這個資源加鎖?
2.線程狀態的改變
先上代碼再說吧:
public class Test { private int counts = 0;// 這個是統計總數 private int inci_1 = 0;// 這個是線程1的變量 private int inci_2 = 0;// 這個是線程2的變量 private int inci_3 = 0;// 這個是線程3的變量 private boolean a = false, b = false, c = false; /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Test t = new Test(); Inc1 inc1 = t.new Inc1(); Inc2 inc2 = t.new Inc2(); Inc3 inc3 = t.new Inc3(); CountAll c = t.new CountAll(); Thread t1 = new Thread(inc1); Thread t2 = new Thread(inc2); Thread t3 = new Thread(inc3); Thread ct = new Thread(c); t1.start(); t2.start(); t3.start(); ct.start(); } //線程1 class Inc1 implements Runnable { public void run() { for (int i = 0; i < 300000000; i++) { inci_1++; } a = true; } } //線程2 class Inc2 implements Runnable { public void run() { for (int i = 0; i < 300000000; i++) { inci_2++; } b = true; } } //線程3 class Inc3 implements Runnable { public void run() { for (int i = 0; i < 300000000; i++) { inci_3++; } c = true; } } //統計器 class CountAll implements Runnable { @Override public void run() { // TODO Auto-generated method stub while (!(a && b&&c)) { counts = inci_1 + inci_2 + inci_3; System.out.println(counts); } counts = inci_1 + inci_2 + inci_3; System.out.println("最后的結果是: "+counts); } } }
那么,解決問題的時刻來了:挖掘機技術到底哪家強?????? (扯一下而已,大家不要介意,請自動忽略,只是為了顯示LZ是個DB)
中間的想法是:給每一個線程分配到一個空間,線程之間不會相互影響,只需要通過一個統計器來更新所有的工作就好了.關鍵在於一點,沒有了鎖.
《深入理解並行編程》中是這樣描述的:
如果一個線程去操作一個加鎖的變量,必須先把這個變量加載進CPU,再修改.這個時候若是還有另一個線程進行操作,那線程1需要把東西通過CPU的System Interconnect發送到線程2,線程1進行擦除操作.然后線程2再進行修改.也就是說:這個多線程效率還不如單線程高
那就回來了,我們為什么還需要去加鎖解鎖?
另外,這個線程間的狀態的辦法是自己想出來的,因為公司電腦沒鼠標,不能上網(新員工),只能擼這么多,等拷回家再發.
1.合法的並行線程會大量增加程序的狀態空間,導致程序難以理解,降低生產率
2.假設我有10000條東西要弄,有100個線程,那么我需要給線程每個分配100的量就好,這樣既兼顧了效率也兼顧了資源
3.編寫並行軟件最重要的考慮是如何進行分割正確的分割問題能夠讓解決辦法簡單,可擴展並且高性能,而不恰當的分割問題則會產生緩慢且復雜的解決方案.
4.在鎖競爭必須降低和同步開銷不是主要局限時,可以使用數據鎖---數據鎖是通過將一塊過大的臨界區分散到各個小的臨界區來減少鎖的競爭.不過這種擴展性的增強帶來的是復雜性的提高,增加了額外的數據結構.
記錄下來,以備查驗