線程安全(java)
引言:一爲T1,T2線程想要調用Dept中的name屬性發生的線程安全問題
二、可變字符串舉例
請求過多會造成內存溢出,如代碼
棧內存溢出:每一個線程對應着一個棧,棧會分配內存,此時如果請求過多,這時候內存不夠了,就會發生棧內存溢出。
棧溢出是指不斷的調用方法,不斷的壓棧,最終超出了棧允許的棧深度,就會發生棧溢出,比如遞歸操作沒有終止,死循環
public class TestString1 {
public static void main(String[] args) throws Exception {
//二、可變字符串舉例
//可變字符串
//StringBuffer(線程安全),StringBuilder
//new:一個線程進來就創建一次
//具體使用Stringbuffer還是StringBuilder還是要看使用場景
//由於目前使用的是多例模式,所以使用StringBuilder不影響線程安全
StringBuilder buff = new StringBuilder();
String s = "";
for (int i = 0; i < 100000000000L; i ++ ){
// s = s + i;
buff.append(i);
}
System.out.println("s = " + buff);
//一、引入
//所謂的線程安全問題,其實是多線程併發執行時,對共享內存中的共享對象的屬性進行修改時
//所導致的數據衝突問題
//分析錯誤原因
//多線程:單線程
//共享內存:多線程共享的內存:堆內存,方法區內存
// :將對象放置在獨享內存中(棧上分配,逃逸分析)
//共享對象:多線程訪問的是同一個對象:Servlet
// : 多例,每一個線程使用一個對象:Struts2
//屬性:對象屬性只有一個,方法沒事(需要壓棧,調用一次壓棧一次,不影響)
//修改:多線程同時修改
Dept2 dept = new Dept();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
dept.name = "開發部";
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(dept.name);
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
dept.name = "執行部";
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(dept.name);
}
});
t2.start();
t1.start();
System.out.println("main方法執行完畢");
//main方法執行完畢
}
}
class Dept{
public String name = "1111";
}
下圖爲線程不安全的:多個線程同時調用name屬性
下圖爲線程安全的