淺析JAVA Lock鎖原理
同樣是鎖,先說說synchronized和lock的區(qū)別:
- synchronized是java關鍵字,是用c++實現(xiàn)的;而lock是用java類,用java可以實現(xiàn)
- synchronized可以鎖住代碼塊,對象和類,但是線程從開始獲取鎖之后開發(fā)者不能進行控制和了解;lock則用起來非常靈活,提供了許多api可以讓開發(fā)者去控制加鎖和釋放鎖等等。
寫個Demo
static Lock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {
lock.lock();//其他沒拿到鎖的卡住不動
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("start to get lock Interruptibly");
lock.unlock(); //看看會發(fā)生什么,注釋掉再看看
lock.lock();
System.out.println("拿到鎖");
lock.unlock();
System.out.println("釋放鎖");
}
});
thread.start();
Thread.sleep(3000);
lock.unlock();
}
我們自己來手寫一下lock接口的tryLock()、lock()和unLock()方法,實現(xiàn)我們自己的myLock。
public class MyLock implements Lock {
//多并發(fā)調(diào)用 0-未占用 大于0-占用
AtomicInteger state = new AtomicInteger();
Thread ownerThread = new Thread();
//等待鎖的隊列
LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue();
@Override
public void lock() {
if (!tryLock()) { //先搶鎖,所以是非公平鎖
//沒拿到鎖,放到隊列中去進行排隊
waiters.add(Thread.currentThread());
//等待被喚醒
for (; ; ) {
if (tryLock()) { //非公平鎖情況下,喚醒過來繼續(xù)獲取鎖
waiters.poll(); //獲取鎖成功把自己從隊列中取出來
return;
} else //獲取鎖失敗
LockSupport.park(); //線程阻塞
}
}
}
@Override
public boolean tryLock() {
if (state.get() == 0) { //如果鎖沒被占用
if (state.compareAndSet(0, 1)) { //如果成功拿到鎖
ownerThread = Thread.currentThread(); //占用鎖線程改為當前線程
return true;
}
}
return false;
}
@Override
public void unlock() {
if (ownerThread != Thread.currentThread()) //占用鎖線程不是當前線程無法釋放鎖
throw new RuntimeException("非法調(diào)用,當前鎖不屬于你");
if (state.decrementAndGet() == 0) //如果成功釋放鎖
ownerThread = null; //占用鎖線程置空
//通知其他線程
// Thread thread = null;
//
// while ((thread = waiters.peek()) != null)
// LockSupport.unpark(thread);
Thread thread = waiters.peek(); //獲取隊列頭部線程,線程還留在隊列中
if (thread != null) {
LockSupport.unpark(thread); //取消阻塞
}
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public Condition newCondition() {
return null;
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
}
幾個注意點:
- 鎖的占用狀態(tài)state是AtomicInteger類型,底層原理是CAS,這是為了保證在多并發(fā)情況下線程安全問題;
- 當線程1釋放鎖成功時,獲取隊列頭部線程但并不取出,因為非公平鎖模式下,隊列頭部線程不一定能獲取到鎖;
- LockSupport的park()和unPark()方法是native方法,可以阻塞,喚醒線程;
Lock默認是非公平鎖,上面實現(xiàn)的也是非公平鎖,小伙伴們可以試一試。
公平鎖和非公平鎖區(qū)別:
先等待先獲取鎖是公平鎖;先等待也不一定先獲取鎖,可能被突然到來的線程獲取到是非公平鎖;
公平鎖的實現(xiàn):
@Override
public void lock() {
checkQueue();//線程來的時候先不獲取鎖,而是先檢查隊列中有沒有等待的線程,如果有,直接放入隊列,如果沒有,再去獲取鎖
if (!tryLock()) { //先搶鎖,所以是非公平鎖
//沒拿到鎖,放到隊列中去進行排隊
waiters.add(Thread.currentThread());
//等待被喚醒
for (; ; ) {
if (tryLock()) { //非公平鎖情況下,喚醒過來繼續(xù)獲取鎖
waiters.poll(); //獲取鎖成功把自己從隊列中取出來
return;
} else //獲取鎖失敗
LockSupport.park(); //線程阻塞
}
}
}
看完的小伙伴可以去看JDK提供的Lock源碼啦。。
以上就是淺析JAVA Lock鎖原理的詳細內(nèi)容,更多關于JAVA Lock鎖原理的資料請關注腳本之家其它相關文章!
- java并發(fā)編程專題(四)----淺談(JUC)Lock鎖
- Java Lock鎖多線程中實現(xiàn)流水線任務
- Java lock同步鎖使用實例解析
- Java多線程 ReentrantLock互斥鎖詳解
- Javas使用Redlock實現(xiàn)分布式鎖過程解析
- java同步之如何寫一個鎖Lock
- 詳解java并發(fā)之重入鎖-ReentrantLock
- Java鎖機制Lock用法示例
- 深入理解java內(nèi)置鎖(synchronized)和顯式鎖(ReentrantLock)
- java基于jedisLock—redis分布式鎖實現(xiàn)示例代碼
- 詳解Java多線程編程中互斥鎖ReentrantLock類的用法
- Java多線程編程之讀寫鎖ReadWriteLock用法實例
相關文章
Springboot項目參數(shù)校驗方式(Validator)
本文介紹了如何在Spring Boot項目中使用`spring-boot-starter-validation`包和注解來實現(xiàn)請求參數(shù)校驗,主要介紹了校驗注解的使用方法、校驗失敗的異常捕獲以及`@Validated`的分組功能2025-02-02
Spring Boot整合Elasticsearch實現(xiàn)全文搜索引擎案例解析
ElasticSearch作為基于Lucene的搜索服務器,既可以作為一個獨立的服務部署,也可以簽入Web應用中。SpringBoot作為Spring家族的全新框架,使得使用SpringBoot開發(fā)Spring應用變得非常簡單,在本案例中我們給大家介紹Spring Boot整合Elasticsearch實現(xiàn)全文搜索引擎2017-11-11
mybatis如何使用注解實現(xiàn)一對多關聯(lián)查詢
這篇文章主要介紹了mybatis如何使用注解實現(xiàn)一對多關聯(lián)查詢的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
Springboot實例講解實現(xiàn)專業(yè)材料認證管理系統(tǒng)流程
這是一個基于java的畢業(yè)設計項目,畢設課題為springboot框架的知識產(chǎn)權服務平臺系統(tǒng),是一個采用b/s結(jié)構的javaweb項目,需要的朋友可以參考下2022-06-06
redis redisson 限流器的實例(RRateLimiter)
這篇文章主要介紹了redis redisson 限流器的實例(RRateLimiter),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07

