摘要:返回與此鎖相關(guān)聯(lián)的給定條件等待的線程數(shù)的估計(jì)。查詢是否有線程正在等待獲取此鎖。為公平鎖,為非公平鎖線程運(yùn)行了獲得鎖定運(yùn)行結(jié)果公平鎖的運(yùn)行結(jié)果是有序的。
系列文章傳送門:
Java多線程學(xué)習(xí)(一)Java多線程入門
Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1)
java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(2)
Java多線程學(xué)習(xí)(三)volatile關(guān)鍵字
Java多線程學(xué)習(xí)(四)等待/通知(wait/notify)機(jī)制
Java多線程學(xué)習(xí)(五)線程間通信知識點(diǎn)補(bǔ)充
Java多線程學(xué)習(xí)(六)Lock鎖的使用
Java多線程學(xué)習(xí)(七)并發(fā)編程中一些問題
系列文章將被優(yōu)先更新于微信公眾號“Java面試通關(guān)手冊”,歡迎廣大Java程序員和愛好技術(shù)的人員關(guān)注。
本節(jié)思維導(dǎo)圖:
思維導(dǎo)圖源文件+思維導(dǎo)圖軟件關(guān)注微信公眾號:“Java面試通關(guān)手冊” 回復(fù)關(guān)鍵字:“Java多線程” 免費(fèi)領(lǐng)取。
一 Lock接口 1.1 Lock接口簡介鎖是用于通過多個線程控制對共享資源的訪問的工具。通常,鎖提供對共享資源的獨(dú)占訪問:一次只能有一個線程可以獲取鎖,并且對共享資源的所有訪問都要求首先獲取鎖。 但是,一些鎖可能允許并發(fā)訪問共享資源,如ReadWriteLock的讀寫鎖。
在Lock接口出現(xiàn)之前,Java程序是靠synchronized關(guān)鍵字實(shí)現(xiàn)鎖功能的。JDK1.5之后并發(fā)包中新增了Lock接口以及相關(guān)實(shí)現(xiàn)類來實(shí)現(xiàn)鎖功能。
雖然synchronized方法和語句的范圍機(jī)制使得使用監(jiān)視器鎖更容易編程,并且有助于避免涉及鎖的許多常見編程錯誤,但是有時您需要以更靈活的方式處理鎖。例如,用于遍歷并發(fā)訪問的數(shù)據(jù)結(jié)構(gòu)的一些算法需要使用“手動”或“鏈鎖定”:您獲取節(jié)點(diǎn)A的鎖定,然后獲取節(jié)點(diǎn)B,然后釋放A并獲取C,然后釋放B并獲得D等。在這種場景中synchronized關(guān)鍵字就不那么容易實(shí)現(xiàn)了,使用Lock接口容易很多。
Lock接口的實(shí)現(xiàn)類:
ReentrantLock , ReentrantReadWriteLock.ReadLock , ReentrantReadWriteLock.WriteLock
Lock lock=new ReentrantLock(); lock.lock(); try{ }finally{ lock.unlock(); }
因?yàn)長ock是接口所以使用時要結(jié)合它的實(shí)現(xiàn)類,另外在finall語句塊中釋放鎖的目的是保證獲取到鎖之后,最終能夠被釋放。
注意: 最好不要把獲取鎖的過程寫在try語句塊中,因?yàn)槿绻讷@取鎖時發(fā)生了異常,異常拋出的同時也會導(dǎo)致鎖無法被釋放。
1.3 Lock接口的特性和常見方法Lock接口提供的synchronized關(guān)鍵字不具備的主要特性:
特性 | 描述 |
---|---|
嘗試非阻塞地獲取鎖 | 當(dāng)前線程嘗試獲取鎖,如果這一時刻鎖沒有被其他線程獲取到,則成功獲取并持有鎖 |
能被中斷地獲取鎖 | 獲取到鎖的線程能夠響應(yīng)中斷,當(dāng)獲取到鎖的線程被中斷時,中斷異常將會被拋出,同時鎖會被釋放 |
超時獲取鎖 | 在指定的截止時間之前獲取鎖, 超過截止時間后仍舊無法獲取則返回 |
Lock接口基本的方法:
方法名稱 | 描述 |
---|---|
void lock() | 獲得鎖。如果鎖不可用,則當(dāng)前線程將被禁用以進(jìn)行線程調(diào)度,并處于休眠狀態(tài),直到獲取鎖。 |
void lockInterruptibly() | 獲取鎖,如果可用并立即返回。如果鎖不可用,那么當(dāng)前線程將被禁用以進(jìn)行線程調(diào)度,并且處于休眠狀態(tài),和lock()方法不同的是在鎖的獲取中可以中斷當(dāng)前線程(相應(yīng)中斷)。 |
Condition newCondition() | 獲取等待通知組件,該組件和當(dāng)前的鎖綁定,當(dāng)前線程只有獲得了鎖,才能調(diào)用該組件的wait()方法,而調(diào)用后,當(dāng)前線程將釋放鎖。 |
boolean tryLock() | 只有在調(diào)用時才可以獲得鎖。如果可用,則獲取鎖定,并立即返回值為true;如果鎖不可用,則此方法將立即返回值為false 。 |
boolean tryLock(long time, TimeUnit unit) | 超時獲取鎖,當(dāng)前線程在一下三種情況下會返回: 1. 當(dāng)前線程在超時時間內(nèi)獲得了鎖;2.當(dāng)前線程在超時時間內(nèi)被中斷;3.超時時間結(jié)束,返回false. |
void unlock() | 釋放鎖。 |
ReentrantLock和synchronized關(guān)鍵字一樣可以用來實(shí)現(xiàn)線程之間的同步互斥,但是在功能是比synchronized關(guān)鍵字更強(qiáng)大而且更靈活。
ReentrantLock類常見方法:
構(gòu)造方法:
方法名稱 | 描述 |
---|---|
ReentrantLock() | 創(chuàng)建一個 ReentrantLock的實(shí)例。 |
ReentrantLock(boolean fair) | 創(chuàng)建一個特定鎖類型(公平鎖/非公平鎖)的ReentrantLock的實(shí)例 |
ReentrantLock類常見方法(Lock接口已有方法這里沒加上):
方法名稱 | 描述 |
---|---|
int getHoldCount() | 查詢當(dāng)前線程保持此鎖定的個數(shù),也就是調(diào)用lock()方法的次數(shù)。 |
protected Thread getOwner() | 返回當(dāng)前擁有此鎖的線程,如果不擁有,則返回 null |
protected Collection |
返回包含可能正在等待獲取此鎖的線程的集合 |
int getQueueLength() | 返回等待獲取此鎖的線程數(shù)的估計(jì)。 |
protected Collection |
返回包含可能在與此鎖相關(guān)聯(lián)的給定條件下等待的線程的集合。 |
int getWaitQueueLength(Condition condition) | 返回與此鎖相關(guān)聯(lián)的給定條件等待的線程數(shù)的估計(jì)。 |
boolean hasQueuedThread(Thread thread) | 查詢給定線程是否等待獲取此鎖。 |
boolean hasQueuedThreads() | 查詢是否有線程正在等待獲取此鎖。 |
boolean hasWaiters(Condition condition) | 查詢?nèi)魏尉€程是否等待與此鎖相關(guān)聯(lián)的給定條件 |
boolean isFair() | 如果此鎖的公平設(shè)置為true,則返回 true 。 |
boolean isHeldByCurrentThread() | 查詢此鎖是否由當(dāng)前線程持有。 |
boolean isLocked() | 查詢此鎖是否由任何線程持有。 |
ReentrantLockTest.java
public class ReentrantLockTest { public static void main(String[] args) { MyService service = new MyService(); MyThread a1 = new MyThread(service); MyThread a2 = new MyThread(service); MyThread a3 = new MyThread(service); MyThread a4 = new MyThread(service); MyThread a5 = new MyThread(service); a1.start(); a2.start(); a3.start(); a4.start(); a5.start(); } static public class MyService { private Lock lock = new ReentrantLock(); public void testMethod() { lock.lock(); try { for (int i = 0; i < 5; i++) { System.out.println("ThreadName=" + Thread.currentThread().getName() + (" " + (i + 1))); } } finally { lock.unlock(); } } } static public class MyThread extends Thread { private MyService service; public MyThread(MyService service) { super(); this.service = service; } @Override public void run() { service.testMethod(); } } }
運(yùn)行結(jié)果:
從運(yùn)行結(jié)果可以看出,當(dāng)一個線程運(yùn)行完畢后才把鎖釋放,其他線程才能執(zhí)行,其他線程的執(zhí)行順序是不確定的。
我們通過之前的學(xué)習(xí)知道了:synchronized關(guān)鍵字與wait()和notify/notifyAll()方法相結(jié)合可以實(shí)現(xiàn)等待/通知機(jī)制,ReentrantLock類當(dāng)然也可以實(shí)現(xiàn),但是需要借助于Condition接口與newCondition() 方法。Condition是JDK1.5之后才有的,它具有很好的靈活性,比如可以實(shí)現(xiàn)多路通知功能也就是在一個Lock對象中可以創(chuàng)建多個Condition實(shí)例(即對象監(jiān)視器),線程對象可以注冊在指定的Condition中,從而可以有選擇性的進(jìn)行線程通知,在調(diào)度線程上更加靈活。
在使用notify/notifyAll()方法進(jìn)行通知時,被通知的線程是有JVM選擇的,使用ReentrantLock類結(jié)合Condition實(shí)例可以實(shí)現(xiàn)“選擇性通知”,這個功能非常重要,而且是Condition接口默認(rèn)提供的。
而synchronized關(guān)鍵字就相當(dāng)于整個Lock對象中只有一個Condition實(shí)例,所有的線程都注冊在它一個身上。如果執(zhí)行notifyAll()方法的話就會通知所有處于等待狀態(tài)的線程這樣會造成很大的效率問題,而Condition實(shí)例的signalAll()方法 只會喚醒注冊在該Condition實(shí)例中的所有等待線程
Condition接口的常見方法:
方法名稱 | 描述 |
---|---|
void await() | 相當(dāng)于Object類的wait方法 |
boolean await(long time, TimeUnit unit) | 相當(dāng)于Object類的wait(long timeout)方法 |
signal() | 相當(dāng)于Object類的notify方法 |
signalAll() | 相當(dāng)于Object類的notifyAll方法 |
1. 使用單個Condition實(shí)例實(shí)現(xiàn)等待/通知機(jī)制:
UseSingleConditionWaitNotify.java
public class UseSingleConditionWaitNotify { public static void main(String[] args) throws InterruptedException { MyService service = new MyService(); ThreadA a = new ThreadA(service); a.start(); Thread.sleep(3000); service.signal(); } static public class MyService { private Lock lock = new ReentrantLock(); public Condition condition = lock.newCondition(); public void await() { lock.lock(); try { System.out.println(" await時間為" + System.currentTimeMillis()); condition.await(); System.out.println("這是condition.await()方法之后的語句,condition.signal()方法之后我才被執(zhí)行"); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void signal() throws InterruptedException { lock.lock(); try { System.out.println("signal時間為" + System.currentTimeMillis()); condition.signal(); Thread.sleep(3000); System.out.println("這是condition.signal()方法之后的語句"); } finally { lock.unlock(); } } } static public class ThreadA extends Thread { private MyService service; public ThreadA(MyService service) { super(); this.service = service; } @Override public void run() { service.await(); } } }
運(yùn)行結(jié)果:
在使用wait/notify實(shí)現(xiàn)等待通知機(jī)制的時候我們知道必須執(zhí)行完notify()方法所在的synchronized代碼塊后才釋放鎖。在這里也差不多,必須執(zhí)行完signal所在的try語句塊之后才釋放鎖,condition.await()后的語句才能被執(zhí)行。
注意: 必須在condition.await()方法調(diào)用之前調(diào)用lock.lock()代碼獲得同步監(jiān)視器,不然會報(bào)錯。
2. 使用多個Condition實(shí)例實(shí)現(xiàn)等待/通知機(jī)制:
UseMoreConditionWaitNotify.java
public class UseMoreConditionWaitNotify { public static void main(String[] args) throws InterruptedException { MyserviceMoreCondition service = new MyserviceMoreCondition(); ThreadA a = new ThreadA(service); a.setName("A"); a.start(); ThreadB b = new ThreadB(service); b.setName("B"); b.start(); Thread.sleep(3000); service.signalAll_A(); } static public class ThreadA extends Thread { private MyserviceMoreCondition service; public ThreadA(MyserviceMoreCondition service) { super(); this.service = service; } @Override public void run() { service.awaitA(); } } static public class ThreadB extends Thread { private MyserviceMoreCondition service; public ThreadB(MyserviceMoreCondition service) { super(); this.service = service; } @Override public void run() { service.awaitB(); } } }
MyserviceMoreCondition.java
public class MyserviceMoreCondition { private Lock lock = new ReentrantLock(); public Condition conditionA = lock.newCondition(); public Condition conditionB = lock.newCondition(); public void awaitA() { lock.lock(); try { System.out.println("begin awaitA時間為" + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName()); conditionA.await(); System.out.println(" end awaitA時間為" + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void awaitB() { lock.lock(); try { System.out.println("begin awaitB時間為" + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName()); conditionB.await(); System.out.println(" end awaitB時間為" + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void signalAll_A() { lock.lock(); try { System.out.println(" signalAll_A時間為" + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName()); conditionA.signalAll(); } finally { lock.unlock(); } } public void signalAll_B() { lock.lock(); try { System.out.println(" signalAll_B時間為" + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName()); conditionB.signalAll(); } finally { lock.unlock(); } } }
運(yùn)行結(jié)果:
只有A線程被喚醒了。
3. 使用Condition實(shí)現(xiàn)順序執(zhí)行
ConditionSeqExec.java
public class ConditionSeqExec { volatile private static int nextPrintWho = 1; private static ReentrantLock lock = new ReentrantLock(); final private static Condition conditionA = lock.newCondition(); final private static Condition conditionB = lock.newCondition(); final private static Condition conditionC = lock.newCondition(); public static void main(String[] args) { Thread threadA = new Thread() { public void run() { try { lock.lock(); while (nextPrintWho != 1) { conditionA.await(); } for (int i = 0; i < 3; i++) { System.out.println("ThreadA " + (i + 1)); } nextPrintWho = 2; //通知conditionB實(shí)例的線程運(yùn)行 conditionB.signalAll(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } }; Thread threadB = new Thread() { public void run() { try { lock.lock(); while (nextPrintWho != 2) { conditionB.await(); } for (int i = 0; i < 3; i++) { System.out.println("ThreadB " + (i + 1)); } nextPrintWho = 3; //通知conditionC實(shí)例的線程運(yùn)行 conditionC.signalAll(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } }; Thread threadC = new Thread() { public void run() { try { lock.lock(); while (nextPrintWho != 3) { conditionC.await(); } for (int i = 0; i < 3; i++) { System.out.println("ThreadC " + (i + 1)); } nextPrintWho = 1; //通知conditionA實(shí)例的線程運(yùn)行 conditionA.signalAll(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } }; Thread[] aArray = new Thread[5]; Thread[] bArray = new Thread[5]; Thread[] cArray = new Thread[5]; for (int i = 0; i < 5; i++) { aArray[i] = new Thread(threadA); bArray[i] = new Thread(threadB); cArray[i] = new Thread(threadC); aArray[i].start(); bArray[i].start(); cArray[i].start(); } } }
運(yùn)行結(jié)果:
通過代碼很好理解,說簡單就是在一個線程運(yùn)行完之后通過condition.signal()/condition.signalAll()方法通知下一個特定的運(yùn)行運(yùn)行,就這樣循環(huán)往復(fù)即可。
注意: 默認(rèn)情況下ReentranLock類使用的是非公平鎖
2.4 公平鎖與非公平鎖Lock鎖分為:公平鎖 和 非公平鎖。公平鎖表示線程獲取鎖的順序是按照線程加鎖的順序來分配的,即先來先得的FIFO先進(jìn)先出順序。而非公平鎖就是一種獲取鎖的搶占機(jī)制,是隨機(jī)獲取鎖的,和公平鎖不一樣的就是先來的不一定先的到鎖,這樣可能造成某些線程一直拿不到鎖,結(jié)果也就是不公平的了。
FairorNofairLock.java
public class FairorNofairLock { public static void main(String[] args) throws InterruptedException { final Service service = new Service(true);//true為公平鎖,false為非公平鎖 Runnable runnable = new Runnable() { @Override public void run() { System.out.println("★線程" + Thread.currentThread().getName() + "運(yùn)行了"); service.serviceMethod(); } }; Thread[] threadArray = new Thread[10]; for (int i = 0; i < 10; i++) { threadArray[i] = new Thread(runnable); } for (int i = 0; i < 10; i++) { threadArray[i].start(); } } static public class Service { private ReentrantLock lock; public Service(boolean isFair) { super(); lock = new ReentrantLock(isFair); } public void serviceMethod() { lock.lock(); try { System.out.println("ThreadName=" + Thread.currentThread().getName() + "獲得鎖定"); } finally { lock.unlock(); } } } }
運(yùn)行結(jié)果:
公平鎖的運(yùn)行結(jié)果是有序的。
把Service的參數(shù)修改為false則為非公平鎖
final Service service = new Service(false);//true為公平鎖,false為非公平鎖
非公平鎖的運(yùn)行結(jié)果是無序的。
我們剛剛接觸到的ReentrantLock(排他鎖)具有完全互斥排他的效果,即同一時刻只允許一個線程訪問,這樣做雖然雖然保證了實(shí)例變量的線程安全性,但效率非常低下。ReadWriteLock接口的實(shí)現(xiàn)類-ReentrantReadWriteLock讀寫鎖就是為了解決這個問題。
讀寫鎖維護(hù)了兩個鎖,一個是讀操作相關(guān)的鎖也成為共享鎖,一個是寫操作相關(guān)的鎖 也稱為排他鎖。通過分離讀鎖和寫鎖,其并發(fā)性比一般排他鎖有了很大提升。
多個讀鎖之間不互斥,讀鎖與寫鎖互斥,寫鎖與寫鎖互斥(只要出現(xiàn)寫操作的過程就是互斥的。)。在沒有線程Thread進(jìn)行寫入操作時,進(jìn)行讀取操作的多個Thread都可以獲取讀鎖,而進(jìn)行寫入操作的Thread只有在獲取寫鎖后才能進(jìn)行寫入操作。即多個Thread可以同時進(jìn)行讀取操作,但是同一時刻只允許一個Thread進(jìn)行寫入操作。
3.2 ReentrantReadWriteLock的特性與常見方法ReentrantReadWriteLock的特性:
特性 | 說明 |
---|---|
公平性選擇 | 支持非公平(默認(rèn))和公平的鎖獲取方式,吞吐量上來看還是非公平優(yōu)于公平 |
重進(jìn)入 | 該鎖支持重進(jìn)入,以讀寫線程為例:讀線程在獲取了讀鎖之后,能夠再次獲取讀鎖。而寫線程在獲取了寫鎖之后能夠再次獲取寫鎖也能夠同時獲取讀鎖 |
鎖降級 | 遵循獲取寫鎖、獲取讀鎖再釋放寫鎖的次序,寫鎖能夠降級稱為讀鎖 |
ReentrantReadWriteLock常見方法:
構(gòu)造方法
方法名稱 | 描述 |
---|---|
ReentrantReadWriteLock() | 創(chuàng)建一個 ReentrantReadWriteLock()的實(shí)例 |
ReentrantReadWriteLock(boolean fair) | 創(chuàng)建一個特定鎖類型(公平鎖/非公平鎖)的ReentrantReadWriteLock的實(shí)例 |
常見方法:
和ReentrantLock類 類似這里就不列舉了。
1. 讀讀共享
兩個線程同時運(yùn)行read方法,你會發(fā)現(xiàn)兩個線程可以同時或者說是幾乎同時運(yùn)行l(wèi)ock()方法后面的代碼,輸出的兩句話顯示的時間一樣。這樣提高了程序的運(yùn)行效率。
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); public void read() { try { try { lock.readLock().lock(); System.out.println("獲得讀鎖" + Thread.currentThread().getName() + " " + System.currentTimeMillis()); Thread.sleep(10000); } finally { lock.readLock().unlock(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
2. 寫寫互斥
把上面的代碼的
lock.readLock().lock();
改為:
lock.writeLock().lock();
兩個線程同時運(yùn)行read方法,你會發(fā)現(xiàn)同一時間只允許一個線程執(zhí)行l(wèi)ock()方法后面的代碼
3. 讀寫互斥
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); public void read() { try { try { lock.readLock().lock(); System.out.println("獲得讀鎖" + Thread.currentThread().getName() + " " + System.currentTimeMillis()); Thread.sleep(10000); } finally { lock.readLock().unlock(); } } catch (InterruptedException e) { e.printStackTrace(); } } public void write() { try { try { lock.writeLock().lock(); System.out.println("獲得寫鎖" + Thread.currentThread().getName() + " " + System.currentTimeMillis()); Thread.sleep(10000); } finally { lock.writeLock().unlock(); } } catch (InterruptedException e) { e.printStackTrace(); } }
測試代碼:
Service service = new Service(); ThreadA a = new ThreadA(service); a.setName("A"); a.start(); Thread.sleep(1000); ThreadB b = new ThreadB(service); b.setName("B"); b.start();
運(yùn)行兩個使用同一個Service對象實(shí)例的線程a,b,線程a執(zhí)行上面的read方法,線程b執(zhí)行上面的write方法。你會發(fā)現(xiàn)同一時間只允許一個線程執(zhí)行l(wèi)ock()方法后面的代碼。記住:只要出現(xiàn)寫操作的過程就是互斥的。
4. 寫讀互斥
和讀寫互斥類似,這里不用代碼演示了。記?。褐灰霈F(xiàn)寫操作的過程就是互斥的。
參考:
《Java多線程編程核心技術(shù)》
《Java并發(fā)編程的藝術(shù)》
如果你覺得博主的文章不錯,歡迎轉(zhuǎn)發(fā)點(diǎn)贊。你能從中學(xué)到知識就是我最大的幸運(yùn)。
歡迎關(guān)注我的微信公眾號:“Java面試通關(guān)手冊”(分享各種Java學(xué)習(xí)資源,面試題,以及企業(yè)級Java實(shí)戰(zhàn)項(xiàng)目回復(fù)關(guān)鍵字免費(fèi)領(lǐng)?。A硗馕覄?chuàng)建了一個Java學(xué)習(xí)交流群(群號:174594747),歡迎大家加入一起學(xué)習(xí),這里更有面試,學(xué)習(xí)視頻等資源的分享。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/69098.html
摘要:無論是互斥鎖,還是自旋鎖,在任何時刻,最多只能有一個保持者,也就說,在任何時刻最多只能有一個執(zhí)行單元獲得鎖。另外在中引入了自適應(yīng)的自旋鎖。和關(guān)鍵字的總結(jié)推薦一 該文已加入開源文檔:JavaGuide(一份涵蓋大部分Java程序員所需要掌握的核心知識)。地址:https://github.com/Snailclimb... 本文是對 synchronized 關(guān)鍵字使用、底層原理、JD...
摘要:因?yàn)槎嗑€程競爭鎖時會引起上下文切換。減少線程的使用。舉個例子如果說服務(wù)器的帶寬只有,某個資源的下載速度是,系統(tǒng)啟動個線程下載該資源并不會導(dǎo)致下載速度編程,所以在并發(fā)編程時,需要考慮這些資源的限制。 最近私下做一項(xiàng)目,一bug幾日未解決,總惶恐。一日頓悟,bug不可怕,怕的是項(xiàng)目不存在bug,與其懼怕,何不與其剛正面。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Jav...
摘要:相比與其他操作系統(tǒng)包括其他類系統(tǒng)有很多的優(yōu)點(diǎn),其中有一項(xiàng)就是,其上下文切換和模式切換的時間消耗非常少。因?yàn)槎嗑€程競爭鎖時會引起上下文切換。減少線程的使用。很多編程語言中都有協(xié)程。所以如何避免死鎖的產(chǎn)生,在我們使用并發(fā)編程時至關(guān)重要。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)syn...
摘要:前情提要深入理解內(nèi)存模型四鎖的釋放獲取建立的關(guān)系鎖是并發(fā)編程中最重要的同步機(jī)制。鎖內(nèi)存語義的實(shí)現(xiàn)本文將借助的源代碼,來分析鎖內(nèi)存語義的具體實(shí)現(xiàn)機(jī)制。請看下篇深入理解內(nèi)存模型六 前情提要 深入理解Java內(nèi)存模型(四)—— volatile 鎖的釋放-獲取建立的happens before 關(guān)系 鎖是java并發(fā)編程中最重要的同步機(jī)制。鎖除了讓臨界區(qū)互斥執(zhí)行外,還可以讓釋放鎖的線程向...
摘要:轉(zhuǎn)載請備注地址多線程學(xué)習(xí)二將分為兩篇文章介紹同步方法另一篇介紹同步語句塊。如果兩個線程同時操作對象中的實(shí)例變量,則會出現(xiàn)非線程安全,解決辦法就是在方法前加上關(guān)鍵字即可。 轉(zhuǎn)載請備注地址: https://blog.csdn.net/qq_3433... Java多線程學(xué)習(xí)(二)將分為兩篇文章介紹synchronized同步方法另一篇介紹synchronized同步語句塊。系列文章傳送門...
閱讀 3161·2021-11-22 09:34
閱讀 2799·2021-09-22 15:28
閱讀 826·2021-09-10 10:51
閱讀 1856·2019-08-30 14:22
閱讀 2279·2019-08-30 14:17
閱讀 2737·2019-08-30 11:01
閱讀 2300·2019-08-29 17:19
閱讀 3664·2019-08-29 13:17