이 기사에서는 Java8의 새로운 StampedLock과 동기화된 Lock을 비교 분석합니다. Java8의 새로운 기능인 StampedLock에 관심이 있는 친구들은 함께 살펴보세요.
Java8은 작은 API 개선입니다. 동기화와 같은 기사는 다중 스레드 동시 프로그래밍programming에서 항상 오래된 주제였습니다. 이는 동기화된 코드를 좋아하지 않을 뿐더러 최악의 경우 애플리케이션의 처리량 및 기타 성능 지표를 감소시킬 것입니다. , 그것은 멈추고 충돌할 것이지만, 이 경우에도 정보의 정확성을 보장해야 하기 때문에 선택의 여지가 없습니다. 따라서 이 기사에서는 동기화된 Lock과 Java 8의 새로운 StampedLock을 비교 분석하기로 결정했습니다. 저는 StampedLock이 모든 사람을 실망시키지 않을 것이라고 믿습니다.
synchronized
Java5 이전에는 주로 동기화를 사용하여 동기화를 수행했습니다. 이는 Java 언어의 키워드로, 메소드나 코드 블록을 수정하는 데 사용되면 최대 하나의 스레드가 동시에 코드를 실행하도록 보장할 수 있습니다.
4개의 서로 다른 동기화 블록이 있습니다.
1. 인스턴스 메서드
2. 정적 메서드
3. 정적 메서드의 동기화 블록
모두가 알아야 합니다. 다음은 코드 예제입니다
synchronized(this) // do operation }
LockJava.util.con
current.locks에 Java 5가 추가한 새로운 API입니다. Lock은 인터페이스입니다. 핵심 메소드는 lock(), Unlock() 및 tryLock()입니다. 구현 클래스에는 ReentrantLock, ReentrantReadWriteLock.WriteLock,
ReentrantReadWriteLock 및 동기화된 잠금이 포함됩니다. 동일한 메모리 의미.
동기화와 달리 Lock은 완전히 Java로 작성되었으며 Java 수준의 JVM 구현과 아무 관련이 없습니다. Lock은 보다 유연한 잠금 메커니즘을 제공하며 잠금 투표, 시간 제한 잠금 대기 및 인터럽트 잠금 대기와 같은 동기화된 많은 기능을 제공하지 않지만 잠금은 코드를 통해 구현되므로 잠금이 해제되도록 보장하기 위해 unLock() into finally{}
다음은 Lock의 코드 예시입니다
rwlock.writeLock().lock(); try { // do operation } finally { rwlock.writeLock().unlock(); }
StampedLock 이는 java8의 java.util.concurrent.locks에 있는 새로운 API입니다.
ReentrantReadWriteLock은 읽기-쓰기 잠금이 없는 경우에만 쓰기 잠금을 얻을 수 있습니다. 이는 비관적 읽기(비관적 읽기)를 구현하는 데 사용할 수 있습니다. 즉, 실행이 읽는 중이면 쓸 다른 실행이 있을 수 있습니다. . 동기화를 유지하기 위해 ReentrantReadWriteLock의 읽기 잠금이 유용할 수 있습니다.
그러나 읽기 수가 많고 쓰기 수가 적은 경우 ReentrantReadWriteLock을 사용하면 쓰기 스레드에서 기아 문제가 발생할 수 있습니다. 즉, 쓰기 스레드가 잠금을 위해 경쟁할 수 없으며 항상 대기 상태입니다.
StampedLock 제어 잠금에는 세 가지 모드(쓰기, 읽기, 낙관적 읽기)가 있습니다. StampedLock 상태는 버전과 모드의 두 부분으로 구성됩니다. 잠금 획득 방법은 해당하는 액세스를 나타내고 제어하는 티켓 스탬프로 숫자를 반환합니다. 잠금 상태. 숫자 0은 액세스 권한이 있는 쓰기 잠금이 없음을 의미합니다. 읽기 잠금은 비관적 잠금과 낙관적 잠금으로 구분됩니다.
소위 낙관적 읽기 모드, 즉 읽기 작업이 많고 쓰기 작업이 적다면 쓰기와 읽기가 동시에 일어날 확률이 매우 작다고 낙관할 수 있으므로 비관 없이 완전하게 사용하세요. 읽기 잠금, 프로그램은 데이터를 읽은 후 쓰기를 통해 데이터가 변경되었는지 확인하고 후속 조치를 취할 수 있습니다(변경 정보를 다시 읽거나
). 이 작은 개선이 큰 차이를 만들 수 있습니다. 프로그램 처리량! ! 다음은 java doc
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의 예입니다. 요약: StampedLock은 ReentrantReadWriteLock보다 저렴하므로 소모가 적습니다.
StampedLock과 ReadWriteLock 성능 비교아래 그림은 ReadWritLock과 비교했을 때 1개의 스레드의 경우 읽기 속도가 약 4배, 쓰기 속도가 1배 정도 되는 것을 보여줍니다.
아래 그림은 6개의 스레드로 읽기 성능도 수십배, 쓰기 성능도 거의 10배가 된 것을 보여줍니다.
아래 그림은 처리량 향상을 보여줍니다.
요약
1. 동기화된 잠금은 일부 모니터링 도구를 통해 모니터링할 수 있을 뿐만 아니라 코드 실행 중에 예외가 발생하면 JVM이 자동으로 잠금을 해제합니다. lock;
2, ReentrantLock, ReentrantReadWriteLock 및 StampedLock은 모두 객체 수준 잠금입니다. 잠금이 해제되도록 하려면 마지막으로 unLock()을 넣어야 합니다.
3. 특히 읽기 스레드가 더 많은 시나리오에서는
4. StampedLock에는 잠금 작업에 다른 방법을 오용하기 쉽습니다.
5. a 좋은 범용 잠금 구현
6. 스레드 증가를 예측할 수 있는 경우 ReentrantLock이 좋은 범용 잠금 구현입니다.
위 내용은 Java 8의 새로운 기능 해석 - StampedLock의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!