多线程——多线程同步的三种实现方法
當(dāng)使用多線程訪問同一個資源的時候,非常容易出現(xiàn)線程安全的問題(例如,當(dāng)多個線程同時對一個數(shù)據(jù)進行修改的時候,會導(dǎo)致某些線程對數(shù)據(jù)的修改丟失)。
因此,需要采用同步機制來解決這種問題。而Java主要提供了三種實現(xiàn)同步機制的方法。今天我們就來認(rèn)識一下~~
一、synchronized關(guān)鍵字
在Java語言中,每個對象都有一個對象鎖與之相關(guān)聯(lián),該鎖表明對象在任何時候只允許被一個線程鎖擁有,當(dāng)一個線程調(diào)用對象的一段synchronized代碼時,需要先獲取這個鎖,然后去執(zhí)行相應(yīng)的代碼,執(zhí)行結(jié)束之后,釋放鎖。
而synchronized關(guān)鍵字主要有兩種用法:synchronized方法和synchronized塊。此外,這個關(guān)鍵字還可以作用于靜態(tài)方法、類或者某個實例,但這都對程序的效率有很大的影響。
1.synchronized方法。在方法的聲明前主要有synchronized關(guān)鍵字,示例如下:
public?synchronized?void?mutiThreadAccess();只要把多個線程對類需要被同步的資源的操作放到mutiThreadAccess()方法中,就能保證這個方法在同一時刻只能被同一個線程訪問,從而保證了多線程訪問的安全性。然而,當(dāng)一個方法的方法體規(guī)模非常大時,把該方法聲明為synchronized會大大影響程序的執(zhí)行效率。為了提高程序的效率,Java提供了synchronized塊。
2.synchronized塊
synchronized塊既可以把任意的代碼段聲明為synchronized,也可以指定上鎖的對象,有非常高的靈活性。其用法如下:
synchronized(syncObject){//訪問synchObject的代碼}二、wait()方法與notify()方法
當(dāng)使用synchronized來修飾某個共享資源時,如果線程A1在執(zhí)行synchronized代碼,另一個線程A2也要同時執(zhí)行同一個對象的同一synchronized代碼時,線程A2將要等到線程A1執(zhí)行完成之后,才能繼續(xù)執(zhí)行。在這種情況下可以使用wait()方法和notify()方法。
在synchronized代碼被執(zhí)行期間,線程可以調(diào)用對象的wait()方法,釋放對象鎖,進入等待狀態(tài),并且可以調(diào)用notify()方法或者notifyAll()方法通知正在等待的其他線程。notify()方法僅喚醒一個線程(即等待隊列中的第一個線程),并允許它去獲得鎖,notifyAll()方法喚醒所有等待這個對象的線程并允許他們?nèi)カ@得鎖,但并不是讓所有喚醒線程都去獲取到鎖,而是讓他們?nèi)ジ偁帯?/strong>
三、Lock
JDK5新增加了Lock接口以及它的一個實現(xiàn)類ReentrantLock(重入鎖),Lock也可以用來實現(xiàn)多線程的同步。具體而言,它提供了如下一些方法來實現(xiàn)多線程的同步:
1.lock()。
這個方法以阻塞的方式獲取鎖,也就是說,如果獲取到鎖了,立即返回;如果別的線程持有鎖,當(dāng)前線程就等待,知道獲取到鎖之后返回。
2.tryLock()。
這個方法與lock()方法不同,它以非阻塞的方式來獲取鎖。此外,它只是常識性地去獲取一下鎖,如果獲取到了鎖,立即返回true,否則立即返回false。
3.tryLock(long?timeout,TimeUnit unit)
如果獲取到鎖,立即返回true,否則會等待參數(shù)給定的時間單元,在等待的過程中,如果獲取到了鎖,就返回true,如果等待超時則返回false。
4.lockInterruptibly()
如果獲取了鎖,立即返回;如果沒有獲取到鎖,當(dāng)前線程處于休眠狀態(tài),直到獲取到鎖,或者當(dāng)前線程被別的線程中斷(會受到InterruptedException異常)。它與lock()方法最大的區(qū)別在于如果lock()方法獲取不到鎖就會一直處于阻塞狀態(tài),而且還會忽略interrupt()方法。
示例如下:
package javatest;import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;public class LockTest {public static void main(String[] args)throws InterruptedException {// TODO Auto-generated method stubfinal Lock lock=new ReentrantLock();lock.lock();Thread t1=new Thread(new Runnable() {public void run() {try {lock.lockInterruptibly();}catch(InterruptedException e){System.out.println("interrupted");}}});t1.start();t1.interrupt();Thread.sleep(1);} }運行結(jié)果如下:?
如果把lock.lockInterruptibly()替換為lock.lock(),編譯器將會提示lock.lock()catch代碼塊無效,這是因為lock.lock()不會拋出異常,由此可見lock()方法會忽略interrupt()引發(fā)的異常。
?
好啦,以上就是實現(xiàn)Java多線程同步的三種方法的相關(guān)總結(jié),如果大家有什么更具體的發(fā)現(xiàn)或者發(fā)現(xiàn)文中有描述錯誤的地方,歡迎留言評論,我們一起學(xué)習(xí)呀~~
?
Biu~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~pia!
總結(jié)
以上是生活随笔為你收集整理的多线程——多线程同步的三种实现方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue.js--实现输出员工工资表
- 下一篇: 蕾塞步进电机不动异常