Synchronized
- 概念:
重量級鎖、重入鎖、jvm 級別鎖
使用:方法:ACC_SYNCHRONIZED、代碼塊 monitorenter\monitorexit
jvm 監視器 - 范圍:方法和代碼塊(物件鎖和類鎖):
- 對于普通同步方法,鎖是當前實體物件, 對于靜態同步方法,鎖是當前類的 Class 物件, 對于同步方法塊,鎖是 Synchonized
括號里配置的物件,
- 場景:
資源競爭
- Lock&ReentrantLock 寫法:
try {
lock.lock();
} finally {
lock.unlock();
}
- void lock() 獲取鎖,呼叫該方法當前執行緒將會獲取鎖,當鎖獲取后,該方法將回傳,
- void lockInterruptibly() throws InterruptedException 可中斷獲取鎖,與 lock()方法不同之處在于該方
- 法會回應中斷,即在鎖的獲取程序中可以中斷當前執行緒
- boolean tryLock() 嘗試非阻塞的獲取鎖,呼叫該方法立即回傳,true 表示獲取到鎖
- boolean tryLock(long time,TimeUnit unit) throws InterruptedException 超時獲取鎖,以下情況會回傳:
- 時間內獲取到了鎖,時間內被中斷,時間到了沒有獲取到鎖,
- void unlock() 釋放鎖
-
統計:
java.util.concurrent.locks.ReentrantLock#getHoldCount
java.util.concurrent.locks.ReentrantLock#getQueuedThreads -
Synchronized 和 ReentrantLock 對比:
- Synchronized:jvm 層級的鎖 自動加鎖自動釋放鎖
- Lock:依賴特殊的 cpu 指令,代碼實作、手動加鎖和釋放鎖、Condition(生產消費模式)
- ReentrantReadWriteLock 讀寫鎖
- 細粒度問題 ,讀是共享的、寫是獨占的
- java8 增加了對讀寫鎖的優化:StampedLock
- 實體代碼
- static Lock可以鎖注當前類 非靜態的只能鎖住當前類的實體物件
package com.itcode.鎖;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author 夏天
* @date 2020年10月29日 22:32
*/
public class ReentrantLock01 implements Runnable {
private static int i = 0;
static Lock lock = new ReentrantLock();
private void add() {
lock.lock();
try {
for (int i1 = 0; i1 < 5000; i1++) {
i++;
}
} finally {
lock.unlock();
}
}
@Override
public void run() {
add();
}
public static void main(String[] args) throws InterruptedException {
for (int j = 0; j < 20; j++) {
i = 0;
ReentrantLock01 sync01 = new ReentrantLock01();
ReentrantLock01 sync02 = new ReentrantLock01();
Thread t1 = new Thread(sync01);
Thread t2 = new Thread(sync02);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
}
}
Lock之tryLock
使用方法:
try {
if(lock.tryLock());
} finally {
//獲取到鎖在釋放 如果不加條件判斷 獲取不到鎖也會進行釋放 會拋出例外IllegalMonitorStateException
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
- tryLock()方法是有回傳值的,它表示用來嘗試獲取鎖,如果獲取成功,則回傳true,如果獲取失敗(即鎖已被其他執行緒獲取),則回傳false,這個方法無論如何都會立即回傳,在拿不到鎖時不會一直在那等待,
- boolean tryLock(long timeout, TimeUnit unit) :
引數1 等待時間,引數2 時間單位
等待指定時間如果還獲取不到鎖回傳false
實體代碼:
package com.itcode.鎖;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author 夏天
* @date 2020年10月29日 22:32
*/
public class ReentrantLock02 implements Runnable {
private static int i = 0;
ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
try {
if (lock.tryLock(4, TimeUnit.SECONDS)) {
System.out.println(Thread.currentThread().getName() + "獲取");
Thread.sleep(6000);
} else {
System.out.println(Thread.currentThread().getName() + "獲取鎖失敗");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//注意 不加這個會報錯 IllegalMonitorStateException 沒有鎖無法解鎖
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLock02 reentrantLock02 = new ReentrantLock02();
Thread t1 = new Thread(reentrantLock02);
Thread t2 = new Thread(reentrantLock02);
t1.start();
t2.start();
t1.join();
t2.join();
}
}
ReentrantReadWriteLock 讀寫鎖
細粒度問題 ,讀是共享的、寫是獨占的
package com.itcode.鎖;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @author 夏天
* @date 2020年10月29日 22:42
* 可以同時讀 上了寫鎖后就不可以讀了
*/
public class ReadWriterLockTest {
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
public String query() {
readLock.lock();
try {
Thread.sleep(50);
System.out.println("讀資料");
return "成功";
} catch (InterruptedException e) {
e.printStackTrace();
return "成功";
} finally {
readLock.unlock();
}
}
public void save() {
writeLock.lock();
try {
System.out.println("保存資料");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
writeLock.unlock();
}
}
/**
* 讀50次
*/
int readCount = 50;
/**
* 寫5次
*/
int writeCount = 5;
public static void main(String[] args) throws InterruptedException, ExecutionException {
ReadWriterLockTest readWriterLockTest = new ReadWriterLockTest();
//new Thread(() -> {
// while (true) {
// readWriterLockTest.query();
// }
//}).start();
//new Thread(() -> {
// while (true) {
// try {
// readWriterLockTest.save();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
//}).start();
CompletableFuture<String> queryFuture = CompletableFuture.supplyAsync(() -> {
while (readWriterLockTest.readCount-- > 0) {
readWriterLockTest.query();
}
return "查詢完成";
});
CompletableFuture<String> saveFuture = CompletableFuture.supplyAsync(() -> {
while (readWriterLockTest.writeCount-- > 0) {
readWriterLockTest.save();
}
return "保存完成";
});
//等待所有執行緒結束 無法接受回傳值 ,接識訓傳值使用anyOf
CompletableFuture.allOf(queryFuture, saveFuture).get();
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/195912.html
標籤:Java
上一篇:Java中的微信支付(2):API V3 微信平臺證書的獲取與重繪
下一篇:Java面向物件之內部類
