我正在研究Java代碼,我需要在其中實現線程。我正在瀏覽JAVA 8 API,並開始瞭解印章。任何人都可以告訴我爲什麼要在多線程中使用StampedLock?什麼是Java中的StampedLock?
在此先感謝。
我正在研究Java代碼,我需要在其中實現線程。我正在瀏覽JAVA 8 API,並開始瞭解印章。任何人都可以告訴我爲什麼要在多線程中使用StampedLock?什麼是Java中的StampedLock?
在此先感謝。
StampedLock是使用ReadWriteLock(由ReentrantReadWriteLock實現)的替代方案。 StampedLock和的ReentrantReadWriteLock之間的主要區別是:
所以,如果你有,你有競爭的情景(否則你不妨使用或簡單的Lock
)和比作者更多的讀者,使用StampedLock可以顯着提高性能。
但是,您應該在跳到結論之前根據您的特定用例來衡量性能。
Heinz Kabutz寫了關於StampedLocks in his newsletter和他也作了a presentation about performance。
爲java.util.concurrent.locks.StampedLock的API文檔說:
StampedLocks設計用作線程安全組件的開發內部工具。他們的使用依賴於他們所保護的數據,對象和方法的內部屬性的知識。它們不是可重入的,因此鎖定的機構不應該調用其他可能嘗試重新獲取鎖定的未知方法(儘管您可以將戳記傳遞給可以使用或轉換它的其他方法)。讀取鎖定模式的使用依賴於相關的代碼段是無副作用的。未經驗證的樂觀閱讀部分不能調用未知的方法來容忍潛在的不一致。郵票使用有限的表示,並且不具有密碼安全性(即,有效的郵票可能是可猜測的)。在連續運行一年後(不止一年),印花值可能會回收。沒有使用或驗證時間長於此期限的圖章可能無法正確驗證。 StampedLocks是可序列化的,但總是反序列化到初始解鎖狀態,所以它們對遠程鎖定沒有用處。
例如, -
class Point {
private double x, y;
private final StampedLock sl = new StampedLock();
void move(double deltaX, double deltaY) { // an exclusively locked method
long stamp = sl.writeLock();
try {
x += deltaX;
y += deltaY;
} finally {
sl.unlockWrite(stamp);
}
}
double distanceFromOrigin() { // A read-only method
long stamp = sl.tryOptimisticRead();
double currentX = x, currentY = y;
if (!sl.validate(stamp)) {
stamp = sl.readLock();
try {
currentX = x;
currentY = y;
} finally {
sl.unlockRead(stamp);
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}
void moveIfAtOrigin(double newX, double newY) { // upgrade
// Could instead start with optimistic, not read mode
long stamp = sl.readLock();
try {
while (x == 0.0 && y == 0.0) {
long ws = sl.tryConvertToWriteLock(stamp);
if (ws != 0L) {
stamp = ws;
x = newX;
y = newY;
break;
}
else {
sl.unlockRead(stamp);
stamp = sl.writeLock();
}
}
} finally {
sl.unlock(stamp);
}
}
}
StampedLock支持讀寫鎖定。與ReadWriteLock相反,StampedLock的鎖定方法返回一個由長整型值表示的圖章。您可以使用這些印章釋放鎖或檢查鎖是否仍然有效。另外加蓋的鎖支持另一種稱爲樂觀鎖的鎖模式。
ExecutorService executor = Executors.newFixedThreadPool(2);
Map<String, String> map = new HashMap<>();
StampedLock lock = new StampedLock();
executor.submit(() -> {
long stamp = lock.writeLock();
try {
Thread.sleep(100);
map.put("test", "INDIA");
} catch (Exception e) {
} finally {
lock.unlockWrite(stamp);
}
});
Runnable readTask =() -> {
long stamp = lock.readLock();
try {
System.out.println(map.get("test"));
Thread.sleep(100);
} catch (Exception e) {
} finally {
lock.unlockRead(stamp);
}
};
executor.submit(readTask);
executor.submit(readTask);
獲取的讀取或經由readLock()或writeLock(寫鎖定)返回稍後用於內的最後塊解鎖郵票。請記住,加蓋的鎖不會實現重入特性。每次鎖定調用都會返回一個新的戳記,並在沒有鎖定的情況下阻止,即使同一個線程已經擁有一個鎖定。所以你必須特別注意不要陷入僵局。
executor.submit(() -> {
long stamp = lock.tryOptimisticRead();
try {
System.out.println("Optimistic Lock Valid: " + lock.validate(stamp));
Thread.sleep(100);
System.out.println("Optimistic Lock Valid: " + lock.validate(stamp));
Thread.sleep(1000);
System.out.println("Optimistic Lock Valid: " + lock.validate(stamp));
} catch (Exception e) {
} finally {
lock.unlock(stamp);
}
});
executor.submit(() -> {
long stamp = lock.writeLock();
try {
System.out.println("Write Lock acquired");
Thread.sleep(100);
} catch (Exception e) {
} finally {
lock.unlock(stamp);
System.out.println("Write done");
}
});
樂觀的讀取鎖是通過調用tryOptimisticRead(),它總是返回郵票沒有如果鎖是實際可用阻止當前線程,不管收購。如果已經有寫鎖定激活,則返回的標記等於零。您可以隨時通過調用lock.validate(stamp)來檢查郵票是否有效。
什麼是_normal multithreading_? – Keppil 2014-09-29 07:10:27
@ SimY4我剛剛閱讀了關於doc中的加蓋鎖。然後我搜索了一下。但是我沒有弄清楚爲什麼我們應該使用它。使用Stamped鎖必須有一些優點,這就是爲什麼Oracle在java 8中引入它的原因。 – Mohit 2014-09-29 07:16:14
@Keppil我編輯了我的問題。謝謝你糾正我。 – Mohit 2014-09-29 07:17:22