《 Java並發編程從入門到精通》Thread安全與不安全
鳥欲高飛先振翅,人求上進先讀書。本文是原書的第3章 Thread安全3.2 什麼是不線程安全。3.3什麼是線程不安全。
3.2 什麼是不安全?
當多個線程同時操作一個數據結構的時候產生了相互修改和串行的情況,沒有保證數據的一致性,我們通常稱之這種設計的代碼為”線程不安全的“。
有這麼一個場景,假設5個用戶,都來給一個數字加1的工作,那麼最後應該是得到加5的結果;看一下下麵的事例;
單個用戶幹活類:Count ;
public class Count {
public int num = 0;
public void add() {
try {
Thread. sleep(5l);//模仿用戶幹活
} catch (InterruptedException e) {
}
num += 1;
System. out.println(Thread.currentThread().getName() + “-” + num);
}
}
用戶類,幹Count 的活;
package demo.thread;
public class ThreadA extends Thread {
private Count count ;
public ThreadA(Count count) {
this.count =count;
}
public void run() {
count.add();
}
}
5個人幹完活:最後的值;
package demo.thread;
public class ThreadMain {
public static void main(String[] args) {
Count count = new Count();
for(int i=0;i<5;i++) {
ThreadA task = new ThreadA(count);
task.start();
}
try {
Thread. sleep(100l);//等5個人幹完活
} catch (InterruptedException e) {
e.printStackTrace();
}
System. out.println(“5個人幹完活:最後的值4″ +count .num );
}
}
運行結果如下:(由於多線程,有不安全問題,其實每次運行下麵的結果都是不一樣的)
Thread-1-1
Thread-0-1
Thread-3-3
Thread-4-2
Thread-2-3
5個人幹完活:最後的值:3
可見不是咱們想要的結果,這就是典型的線程不安全問題;而我們實際工作中,特別是web項目Service和servlet一般都是單例共享變量的就會及其容易出現,多個用戶之間的數據串掉了,從而導致最終數據庫裏麵所需要統計的數據不對;
3.3 什麼是安全?
我們還看上麵的例子隻對單個用戶幹活類:Count ;做如下修改 添加synchronized 關鍵字;
package demo.thread;
public class Count {
public int num = 0;
public synchronized void add() {
try {
Thread. sleep(5l);//模仿用戶幹活
} catch (InterruptedException e) {
}
num += 1;
System. out.println(Thread.currentThread().getName() + “-” + num);
}
}
運行結果如下:
Thread-0-1
Thread-4-2
Thread-3-3
Thread-2-4
Thread-1-5
5個人幹完活:最後的值5
而這次,每次幹活都是一樣的結果,這就叫線程安全,就是不管多少個用戶過來,都保證咱們的數據的高度一致性和準確性就叫線程安全的;這裏我們引用了synchronized 的同步鎖的機製,這個後麵會講到,來保證了我們的線程安全性;
什麼是線程安全性呢?是不是一定要加鎖才是線程安全性的呢?個人感覺隻要你代碼裏麵沒有變量互串,線程之間互不影響,例如server的設計方法,就是線程安全的,例如上麵五個人幹了同一件事情,如果讓5個人幹5件不一樣的事情,或者1個人幹5件事情,那也是安全的。而不安全在java工作中主要針對單例模式的應用而言的,怎麼保證一件事情被一群人幹完,又快又正確;
想實現線程安全大概有三種方法:
1:多實例,也就是不用單例模式了。
2:使用java.util.concurrent下麵的類庫。
3:使用鎖機製synchronized,lock方式。
最後更新:2017-05-22 13:31:50