【Java多線程】(二)多線程同步

接上文。


一:多線程同步

當使用多線程訪問一個資源的時候,容易出現線程安全的問題。比如A、B兩個線程模擬兩個用戶銀行轉賬業務。剛開始兩人各有1000元。首先A、查詢自己餘額爲1000,然後提現100,並把餘額修改爲900。假如提現是一個非常耗時的操作,在完成這個操作之前,B給A轉了賬100。轉完賬以後將A的餘額修改爲1100。此時A提現完成,並將餘額修改爲900。可見這個結果時不合理的。這就是一個多線程同時訪問的安全問題。這個時候就需要同步機制。

解決多線程的方式其實就是枷鎖。一次只能允許一個線程執行某段代碼,或者讀取修改某個變量。

方法一:synchronized關鍵字。

在Java語言中,每個對象都有一個對象鎖,該鎖表明對象在任何時候只允許一個線程所擁有。當線程執行synchronized代碼時,首先需要獲取這個鎖,當代碼執行結束之後釋放鎖。從而使得每次只有一個線程訪問執行代碼,從而不會出現多線程安全問題。

方法二: Lock關鍵字

JDK5之後添加了Lock接口,以及它的一個實現類ReentrantLock(重入鎖)。也可以實現方法一的功能。主要有一下幾個關鍵方法:

1.lock()。以阻塞的方式獲取鎖。即如果獲取鎖,返回。獲取不到鎖,等待,直到獲取鎖。

2.tryLock()。字面意思,嘗試性獲取鎖。嘗試獲取一下鎖,成功返回true;否則,返回false。

3.lockInterruptibly()。類似1,不同的時,如果獲取不到鎖,就等待,但是也能被打斷。

二:Synchronized與Lock區別

1:用法不同。

Synchronized可以加在方法或者代碼塊上,託管給jvm執行,但是lock必須顯示的指定起始和終止位置,鎖定是通過代碼完成。

2. 性能不一樣

在資源競爭不激烈的時候,synchronized性能好。激烈的時候,lock的實現類reentrantLock性能基本保持不變,synchronized性能下降很快

3. 鎖機制不一樣

Synchronized獲得多個鎖的時候必須以相反的順序釋放,並且是自動的解鎖,不會引發死鎖。Lock必須人工手動在finally塊釋放鎖。否則會引起死鎖。

三:sleep()與wait()區別

1.原理不相同

sleep()是Thread的靜態方法,是線程用來控制自身流程的。他會暫停當前線程的執行,進行休眠,並把執行的機會讓給其他線程。當休眠時間到了,便會自動醒來。而wait()方法則不一樣,是Object類中的方法,用於進城之間的通信。使得當前線程停止執行,直到其他線程執行notify()或者是notifyAll()方法,纔會喚醒。當然,也可以給自己設定一個醒來的時間。

2.處理機制不一樣。

sleep()是讓線程暫停一段時間,並不釋放鎖,且不涉及線程之間的通信。但是wait()方法則是直接釋放鎖,別的線程可以獲取鎖。

3.作用域不一樣。

sleep()可以放在任何地方,wait()需要咋同步控制方法或者同步語句塊中使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章