Java多線程編程之Lock用法實例
鎖是控制多個線程對共享資源進(jìn)行訪問的工具。通常,鎖提供了對共享資源的獨(dú)占訪問。一次只能有一個線程獲得鎖,對共享資源的所有訪問都需要首先獲得鎖。不過,某些鎖可能允許對共享資源并發(fā)訪問,如 ReadWriteLock(維護(hù)了一對相關(guān)的鎖,一個用于只讀操作,另一個用于寫入操作) 的讀寫鎖。
1、Lock提供了無條件的、可輪詢的、定時的、可中斷的鎖獲取操作,所有加鎖和解鎖的方法都是顯式的。
public interface Lock{
void lock(); //加鎖
//優(yōu)先考慮響應(yīng)中斷,而不是響應(yīng)鎖定的普通獲取或重入獲取
void lockInterruptibly() throws InterruptedException;
boolean tryLock(); //可定時和可輪詢的鎖獲取模式
boolean tryLock(long timeout,TimeUnit unit) throws InterruptedException;
void unlock(); //解鎖
Condition newCondition();
}
2、ReentrantLock實現(xiàn)了lock接口,跟synchronized相比,ReentrantLock為處理不可用的鎖提供了更多靈活性。
3、使用lock接口的規(guī)范形式要求在finally塊中釋放鎖lock.unlock()。如果鎖守護(hù)的代碼在try塊之外拋出了異常,它將永遠(yuǎn)不會被釋放。
以下模擬Lock用法:假設(shè)有兩個線程(A線程、B線程)去調(diào)用print(String name)方法,A線程負(fù)責(zé)打印'zhangsan'字符串,B線程負(fù)責(zé)打印'lisi'字符串。
1、當(dāng)沒有為print(String name)方法加上鎖時,則會產(chǎn)生A線程還沒有執(zhí)行完畢,B線程已開始執(zhí)行,那么打印出來的name就會出現(xiàn)如下問題。
2、當(dāng)為print(String name)方法加上鎖時,則會產(chǎn)生A執(zhí)行完畢后,B線程才執(zhí)行print(String name)方法,達(dá)到互斥或者說同步效果。
package com.ljq.test.thread;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 用Lock替代synchronized
*
* @author Administrator
*
*/
public class LockTest {
public static void main(String[] args) {
new LockTest().init();
}
private void init() {
final Outputer outputer = new Outputer();
//A線程
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.output("zhangsan");
}
}
}).start();
//B線程
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.output("lisi");
}
}
}).start();
}
static class Outputer {
Lock lock = new ReentrantLock();
/**
* 打印字符
*
* @param name
*/
public void output(String name) {
int len = name.length();
lock.lock();
try {
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
} finally {
lock.unlock();
}
}
}
}
相關(guān)文章
Springboot把外部依賴包納入Spring容器管理的兩種方式
這篇文章主要給大家介紹了Springboot把外部依賴包納入Spring容器管理的兩種方式,Spring.factories和org.springframework.boot.autoconfigure.AutoConfiguration.imports,有感興趣的小伙伴可以參考閱讀本文2023-07-07
SpringBatch數(shù)據(jù)讀取的實現(xiàn)(ItemReader與自定義讀取邏輯)
本文主要介紹了SpringBatch數(shù)據(jù)讀取的實現(xiàn), 文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-04-04
Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(2)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你2021-07-07
解決OkHttp接收gzip壓縮數(shù)據(jù)返回亂碼問題
這篇文章主要介紹了解決OkHttp接收gzip壓縮數(shù)據(jù)返回亂碼問題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
使用springCloud+nacos集成seata1.3.0搭建過程
這篇文章主要介紹了使用springCloud+nacos集成seata1.3.0搭建過程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08

