多線程不安全,主要由於cpu分配機制,誰得到了cpu誰就能執行,所以形成了線程的不安全.安全
那麼,如何找出問題呢?markdown
1.明確哪些代碼是多線程運行的代碼,
2.明確共享數據
3.明確多線程運行代碼中哪些語句是操做共享數據.多線程
根據以上三部.下面看例子,ide
package com.niuli.develop;
public class Test {
public static void main (String [] args) {
Cus c = new Cus();
new Thread(c).start();
new Thread(c).start();
}
}
class Bank{
private int sum = 0;
public void add(int n) {
sum = sum + n;
System.out.println("sum= "+sum);
}
}
class Cus implements Runnable{
Bank b = new Bank();
@Override
public void run() {
for (int i = 0; i < 3; i++) {
b.add(100);
}
}
}
很簡單的例子,
首先第一步,找到多線程運行的代碼函數
也就是run方法裏面的代碼
for (int i = 0; i < 3; i++) {
b.add(100);
}
另外這裏用到了Add方法,因此add也算
public void add(int n) {
sum = sum + n;
System.out.println("sum= "+sum);
}
第二步,找到共享數據性能
Bank b = new Bank();
private int sum = 0;
第三步,明確多線程使用的共享數據.
首先對於數據b就一條語句使用了這個共享變量,所以不會出現線程不安全,可是對於sum,有兩條語句使用的,因此就會出現線程安全問題,spa
解決辦法,同步塊線程
Object obj = new Object();
public void add(int n) {
synchronized (obj) {
sum = sum + n;
System.out.println("sum= "+sum);
}
}
或者,同步函數code
public synchronized void add(int n) {
sum = sum + n;
System.out.println("sum= "+sum);
}
以上就是線程安全的解決辦法,同步機制雖然遊俠,可是帶來了必定的性能損耗,因此,對操做共享數據的部分執行同步,儘可能減小這種損耗對象
補充:
若是同步函數是靜態的,那麼使用的鎖就必須是所在類的字節碼文件對象,也就是 類名.class,解釋來講,靜態是和類一塊兒加載的,因此在靜態加載的時候是不可能有object的對象,因此鎖就必須用在靜態加在以前的一個對象.