Lock鎖的基本使用
在Java中,Lock是一個(gè)接口,它提供了比synchronized關(guān)鍵字更高級(jí)的線程同步機(jī)制。使用Lock接口可以創(chuàng)建更復(fù)雜和靈活的同步結(jié)構(gòu)。
Lock接口的常用實(shí)現(xiàn)類(lèi)有ReentrantLock和ReentrantReadWriteLock,它們提供了可重入的互斥鎖和讀寫(xiě)鎖。
相比synchronized來(lái)實(shí)現(xiàn)同步,使用Lock實(shí)現(xiàn)同步主要有以下差異性:
- ?使用synchronized關(guān)鍵字時(shí),鎖的控制和釋放是在synchronized同步代碼塊的開(kāi)始和結(jié)束位置。而在使用Lock實(shí)現(xiàn)同步時(shí),鎖的獲取和釋放可以在不同的代碼塊、不同的方法中。這一點(diǎn)是基于使用者手動(dòng)獲取和釋放鎖的特性。
- ?Lock接口提供了試圖獲取鎖的tryLock()方法,在調(diào)用tryLock()獲取鎖失敗時(shí)返回false,這樣線程可以執(zhí)行其它的操作 而不至于使線程進(jìn)入休眠。tryLock()方法可傳入一個(gè)long型的時(shí)間參數(shù),允許在一定的時(shí)間內(nèi)來(lái)獲取鎖。
- ?Lock接口的實(shí)現(xiàn)類(lèi)ReentrantReadWriteLock提供了讀鎖和寫(xiě)鎖,允許多個(gè)線程獲得讀鎖、而只能有一個(gè)線程獲得寫(xiě)鎖。讀鎖和寫(xiě)鎖不能同時(shí)獲得。實(shí)現(xiàn)了讀和寫(xiě)的分離,這一點(diǎn)在需要并發(fā)讀的應(yīng)用中非常重要,如lucene允許多個(gè)線程讀取索引數(shù)據(jù)進(jìn)行查詢但只能有一個(gè)線程負(fù)責(zé)索引數(shù)據(jù)的構(gòu)建。
- ?基于以上3點(diǎn),lock來(lái)實(shí)現(xiàn)同步具備更好的性能。
使用Lock:
創(chuàng)建Lock對(duì)象。
// 創(chuàng)建Lock對(duì)象
Lock lock = new ReentrantLock();
```
在需要進(jìn)行同步的代碼塊中,通過(guò)調(diào)用`lock()`方法來(lái)獲取鎖。
lock.lock();
try {
// 同步的代碼
} finally {
// 在finally塊中釋放鎖,以確保鎖的釋放
lock.unlock();
}
```
示例代碼如下,多種方式進(jìn)行代碼塊同步:
package ch12;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @copyright 2003-2024
* @author qiao wei
* @date 2024-01-10
* @version 1.0
* @brief
* @history
*/
public class SellTicketThread extends Thread {
public SellTicketThread() {
ticket = 0;
lock = new ReentrantLock();
}
@Override
public void run() {
super.run();
// run01();
runUseLock04();
}
private void runUseSynchronized() {
while (true) {
synchronized (SellTicketThread.class) {
if (100 >= ticket) {
++ticket;
// sleep(100);
System.out.println(getName() + "正在賣(mài)第" + ticket + "門(mén)票");
} else {
break;
}
}
}
}
/**
* @author qiao wei
* @brief 先處理,后break流程。多處使用類(lèi)Lock的unlock方法。
* @param
* @return
* @throws
* @history
*/
private void runUseLock01() {
while (true) {
if (100 >= ticket) {
lock.lock();
if (100 >= ticket) {
++ticket;
System.out.println(getName() + "正在賣(mài)第" + ticket + "門(mén)票");
} else {
lock.unlock();
break;
}
lock.unlock();
} else {
// 退出while循環(huán)語(yǔ)句。
break;
}
}
}
/**
* @author qiao wei
* @brief 先處理,后break流程。使用try/finally流程處理類(lèi)Lock的unlock方法。
* @param
* @return
* @throws
* @history
*/
private void runUseLock02() {
while (true) {
if (100 >= ticket) {
try {
lock.lock();
if (100 >= ticket) {
++ticket;
System.out.println(getName() + "正在賣(mài)第" + ticket + "門(mén)票");
} else {
break;
}
} finally {
// 唯一解鎖處。
lock.unlock();
}
} else {
// 退出while循環(huán)語(yǔ)句。
break;
}
}
}
/**
* @author qiao wei
* @brief 先break,后處理流程。多處使用類(lèi)Lock的unlock方法。
* @param
* @return
* @throws
* @history
*/
private void runUseLock03() {
while (true) {
if (100 == ticket) {
break;
} else {
lock.lock();
if (100 == ticket) {
lock.unlock();
// 退出while循環(huán)語(yǔ)句。
break;
} else {
++ticket;
System.out.println(getName() + "正在賣(mài)第" + ticket + "門(mén)票");
}
lock.unlock();
}
}
}
/**
* @author qiao wei
* @brief 先break,后處理流程。使用try/finally流程處理類(lèi)Lock的unlock方法。
* @param
* @return
* @throws
* @history
*/
private void runUseLock04() {
while (true) {
if (100 == ticket) {
break;
} else {
lock.lock();
try {
if (100 == ticket) {
break;
} else {
++ticket;
System.out.println(getName() + "正在賣(mài)第" + ticket + "門(mén)票");
}
} finally {
lock.unlock();
}
}
}
}
/**
* @author qiao wei
* @brief 要出售的總票數(shù)。
*/
private static int ticket;
/**
* @author qiao wei
* @brief 同步鎖。
*/
private static Lock lock;
}
測(cè)試驗(yàn)證:
package ch12;
/**
* @copyright 2003-2024
* @author qiao wei
* @date 2024-01-10
* @version 1.0
* @brief
* @history
*/
public class TestSynchronized {
public TestSynchronized() {}
public static void main(String[] args) {
SellTicketThread thread01 = new SellTicketThread();
SellTicketThread thread02 = new SellTicketThread();
SellTicketThread thread03 = new SellTicketThread();
thread01.start();
thread02.start();
thread03.start();
}
}
注意事項(xiàng):文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-781568.html
加鎖(lock或synchronized)必須在循環(huán)(while)里面,不軟會(huì)導(dǎo)致一個(gè)線程占用所有資源,而不是多線程切換。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-781568.html
到了這里,關(guān)于Java多線程:Lock鎖(未完待續(xù))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!