中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java線程安全與同步實例分析

發布時間:2022-04-14 13:50:36 來源:億速云 閱讀:145 作者:iii 欄目:開發技術

本篇內容介紹了“Java線程安全與同步實例分析”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

線程安全問題

多個線程可能會共享(訪問)同一個資源

比如訪問同一個對象,同一個變量,同一個文件

當多個線程訪問同一塊資源時,很容易引發數據錯亂和數據安全問題,稱為線程安全問題

什么情況下會出現線程安全問題

多個線程共享同一個資源

且至少有一個線程正在執行寫的操作

實例:

存錢取錢問題

分別有存錢和取錢2個線程

   存錢                      取錢
   線程1         余額         線程2
   1000  《----1000------》 1000
   1000+1000-----》2000
                500 《-----1000-500

正確:結束后余額應該是1500,而不是500

買票問題

有賣票2個線程

   賣票                      賣票
   線程1         票數         線程2
   1000  《----1000------》 1000
   1000-1-----》999
                999 《-----1000-1

正確:結束后余額應該是998,而不是999

買票問題錯誤(未線程同步)實例:

public class love implements Runnable{
    private int piao=3000;//有3000張票
    public boolean sale() {//ture代表還有票;false代表沒有票了
        if(piao<1) return false;
         piao--;//賣1張票
         
         //細化piao--;
         //寄存器=piao;
         //寄存器=寄存器-1;
         //piao=寄存器;
         
         String sk =Thread.currentThread().getName();//獲取當前線程(買票窗口)的名字
         System.out.println(sk+"賣了1張票,還剩下"+piao+"張");
         return piao>1;
    }
    public void run() {
         while(sale());//循環執行;直至賣完票返回false
    }
}
 
public class Main {
    public static void main(String[] a) {
        love tjlove =new love();
        for(int i=1;i<=4;i++) {//循環4次;產生4個線程(窗口)賣票
            Thread tj = new Thread(tjlove());
            tj.setName(""+i);
            tj.start();
        }
    }
}

部分輸出結果:

Java線程安全與同步實例分析

線程安全問題

分析問題

線程A和B對類中1個變量值為17進行+1操作
最終結果為2個18

解決方案

加鎖:

過程:首先線程A先訪問到這個17,讀上來后進行加鎖并進去+1的操作改為18
并且17在加鎖期間其它線程都不能訪問
改完之后再進行寫入,然后再解鎖17
然后再由線程B去訪問它,再進行加鎖,重復上面操作變成19再解鎖
這樣做能保證在同一時間只有1個線程去訪問它,這樣就保證了安全;之前錯誤是由于這些線程一起去訪問了它

線程同步

剛剛所說的加鎖操作便是線程同步技術

可以使用線程同步技術來解決線程安全問題

線程同步在Java里有2種做法:

1.同步語句

2.同步方法

同步語句

public class love implements Runnable{
	private int piao=3000;//本人cpu單核性能過強,數據量大些才能看到是4個線程在賣票
	public boolean sale() {
		synchronized(this) {//1個線程獲取這個對象的鎖,并加鎖;    synchronized作用于整個語句
		//this指向當前對象
		//不能用new Object();這樣會產生新的對象,產生新的鎖
		//把this換成"123",效果基本一樣;因為其存在常量值里,每次訪問的對象一樣
			if(piao<1) return false;
			piao--;
			String sk =Thread.currentThread().getName();
			System.out.println(sk+"賣了1張票,還剩下"+piao+"張");
			return piao>0;
			}
	}
	public void run() {
		 while(sale());
	}
}

部分輸出結果:

Java線程安全與同步實例分析

synchronize(obj)的原理

1.每個對象都有一個與它相關的內部鎖(intrinsic lock)或者叫監視器鎖(monitor lock)

2.第一個執行到同步語句的線程可以獲得 obj 的內部鎖,在執行完同步語句中的代碼后釋放此鎖

3.只要一個線程持有了內部鎖,那么其它線程在同一時刻將無法再獲得此鎖

? 當它們試圖獲取此鎖時,將會進入BLOCKED狀態

4.多個線程訪問同一個 synchronized(obj)語句時

obj必須是同一個對象,才能起到同步的作用

同步方法

public class love implements Runnable{
    private int piao=3000;
    public synchronized boolean sale() { //synchronized作用于整個方法
            if(piao<1) return false;
            piao--;
            String sk =Thread.currentThread().getName();
            System.out.println(sk+"賣了1張票,還剩下"+piao+"張");
            return piao>0;
    }
    public void run() {
         while(sale());
    }
}

synchronized不能修飾構造方法

同步方法的本質

實例方法:synchronized (this)

靜態方法:synchronized (Class對象)

同步語句比同步方法更靈活一點

同步語句可以精確控制需要加鎖的代碼范圍,減少處于BLOCKED狀態的線程,充分利用勞動力

使用了線程同步技術后

雖然解決了線程安全問題,但是降低了程序的執行效率

因為加了鎖就會有處于等待的線程,多了加鎖解鎖的操作

所以在真正有必要的時候,才使用線程同步技術

“Java線程安全與同步實例分析”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

望谟县| 天全县| 叙永县| 横峰县| 防城港市| 五华县| 普兰县| 光山县| 舞钢市| 襄汾县| 安泽县| 铜川市| 华安县| 化隆| 军事| 广宁县| 伊金霍洛旗| 齐河县| 外汇| 邹平县| 荥经县| 柳河县| 文昌市| 波密县| 呼图壁县| 寻乌县| 峡江县| 合山市| 从江县| 黑水县| 曲靖市| 德格县| 来凤县| 灌云县| 开原市| 博客| 定日县| 海南省| 克什克腾旗| 兴隆县| 淅川县|