Java多線程編程之Lock用法實(shí)例
鎖是控制多個(gè)線程對(duì)共享資源進(jìn)行訪問的工具。通常,鎖提供了對(duì)共享資源的獨(dú)占訪問。一次只能有一個(gè)線程獲得鎖,對(duì)共享資源的所有訪問都需要首先獲得鎖。不過,某些鎖可能允許對(duì)共享資源并發(fā)訪問,如 ReadWriteLock(維護(hù)了一對(duì)相關(guān)的鎖,一個(gè)用于只讀操作,另一個(gè)用于寫入操作) 的讀寫鎖。
1、Lock提供了無條件的、可輪詢的、定時(shí)的、可中斷的鎖獲取操作,所有加鎖和解鎖的方法都是顯式的。
public interface Lock{
void lock(); //加鎖
//優(yōu)先考慮響應(yīng)中斷,而不是響應(yīng)鎖定的普通獲取或重入獲取
void lockInterruptibly() throws InterruptedException;
boolean tryLock(); //可定時(shí)和可輪詢的鎖獲取模式
boolean tryLock(long timeout,TimeUnit unit) throws InterruptedException;
void unlock(); //解鎖
Condition newCondition();
}
2、ReentrantLock實(shí)現(xiàn)了lock接口,跟synchronized相比,ReentrantLock為處理不可用的鎖提供了更多靈活性。
3、使用lock接口的規(guī)范形式要求在finally塊中釋放鎖lock.unlock()。如果鎖守護(hù)的代碼在try塊之外拋出了異常,它將永遠(yuǎn)不會(huì)被釋放。
以下模擬Lock用法:假設(shè)有兩個(gè)線程(A線程、B線程)去調(diào)用print(String name)方法,A線程負(fù)責(zé)打印'zhangsan'字符串,B線程負(fù)責(zé)打印'lisi'字符串。
1、當(dāng)沒有為print(String name)方法加上鎖時(shí),則會(huì)產(chǎn)生A線程還沒有執(zhí)行完畢,B線程已開始執(zhí)行,那么打印出來的name就會(huì)出現(xiàn)如下問題。
2、當(dāng)為print(String name)方法加上鎖時(shí),則會(huì)產(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配置MyBatis-Plus實(shí)現(xiàn)增刪查改
本文主要介紹了SpringBoot配置MyBatis-Plus實(shí)現(xiàn)增刪查改,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
Spring中的之啟動(dòng)過程obtainFreshBeanFactory詳解
這篇文章主要介紹了Spring中的之啟動(dòng)過程obtainFreshBeanFactory詳解,在refresh時(shí),prepareRefresh后,馬上就調(diào)用了obtainFreshBeanFactory創(chuàng)建beanFactory以及掃描bean信息(beanDefinition),并通過BeanDefinitionRegistry注冊到容器中,需要的朋友可以參考下2024-02-02
Java使用MySQL實(shí)現(xiàn)連接池代碼實(shí)例
這篇文章主要介紹了Java使用MySQL實(shí)現(xiàn)連接池代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
使用eclipse快速新建spirngboot項(xiàng)目的方法
本篇文章主要介紹了使用eclipse快速新建spirngboot項(xiàng)目的方法,具有一定的參考價(jià)值,有興趣的可以了解一下2017-04-04
MyBatis傳入?yún)?shù)的實(shí)例代碼
這篇文章主要介紹了MyBatis傳入?yún)?shù)的實(shí)例代碼的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06
Spring boot如何通過@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)及多線程配置
這篇文章主要介紹了Spring boot如何通過@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)及多線程配置,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
Springboot如何連接遠(yuǎn)程服務(wù)器上的數(shù)據(jù)庫實(shí)踐
本文主要介紹了Springboot如何連接遠(yuǎn)程服務(wù)器上的數(shù)據(jù)庫實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04

