1. Longadder
Atomiclong과 비슷한 방식으로 사용되지만 Atomiclong보다 성능이 향상됩니다.
Longadder와 Atomiclong은 모두 원자 연산을 사용하여 성능을 향상시킵니다. 그러나 Longadder는 Atomiclong을 기반으로 핫스팟 분리를 수행합니다. 핫스팟 분리는 잠긴 작동에서 잠금 입자 크기를 줄이며 잠금을 여러 자물쇠로 분리하여 성능을 향상시키는 것과 유사합니다. 잠금 장치에서 유사한 방법을 사용하여 CAS의 성공률을 높이고 성능을 향상시킬 수 있습니다.
Longadder 회로도 :
Atomiclong의 구현 방법은 내부에 값 변수가 있다는 것입니다. 여러 스레드가 자체 증가하고 자체적으로 제거되면 동시성의 원자력을 보장하기 위해 CAS 명령을 통해 기계 명령어 수준에서 작동합니다. Atomiclong의 효율성을 제한하는 유일한 이유는 동시성이 높습니다. 동시 동시성이 높으면 CAS가 고장 확률이 높고 재 시도 시간이 많고 스레드가 더 많을수록 CAS의 실패 가능성이 높아져 악순환이되고 Atomiclong의 효율이 줄어 듭니다.
Longadder는 값을 여러 세포로 나누고 모든 셀을 값에 추가합니다. 따라서 Longadder를 추가하고 빼면 다른 셀에서만 작동하면됩니다. 다른 스레드는 다른 셀에서 CAS 작업을 수행합니다. 물론 CAS의 성공률은 높습니다 (상상 3+2+1 = 6, 하나의 스레드 3+1, 다른 스레드 2+1, 마지막으로 8, Longadder는 곱셈 및 분할을위한 API가 없습니다).
그러나 동시성 수가 그다지 높지 않은 경우, 여러 세포로 분할되면 셀과 합계를 유지해야합니다. 이는 Atomiclong의 구현만큼 효율적이지 않습니다. Longadder는이 문제를 해결하기 위해 영리한 방법을 사용했습니다.
초기 상황에서 Longadder와 Atomiclong은 동일합니다. CAS가 실패 할 때만 값은 셀로 분할됩니다. 실패가 이루어질 때마다 셀의 수가 증가합니다. 이것은 또한 낮은 동시성에서 효율적입니다. 높은 동시성에서,이 "적응 형"처리 방법은 특정 수의 셀에 도달 한 후에 실패하지 않으며 효율이 크게 향상 될 것입니다.
Longadder는 시간 동안 공간을 교환하는 전략입니다.
2. 완전한 영향
완료 단계 인터페이스 (40 개 이상의 메소드)를 구현하며, 대부분 기능 프로그래밍에 사용됩니다. 스트리밍 통화를 지원합니다
Completomputure는 Java 8의 향상된 버전입니다.
간단한 구현 :
import java.util.concurrent.completableFuture; public class askthread emplements runnable {completableFuture <integer> re = null; public askthread (wombledablefuture <integer> re) {this.re = re; } @override public void run () {int myre = 0; {myre = re.get () * re.get (); } catch (예외 e) {} system.out.println (myre); } public static void main (String [] args)은 InterruptedException {Final TompletableFuture <integer> future = new wompletableFuture <integer> (); 새 스레드 (New AskThread (Future)). start (); // 장기 계산 프로세스 시뮬레이션 스레드 .sleep (1000); // 완료 결과를 알리십시오. Future.complete (60); }} 미래에 대한 가장 비판적인 점은 기다렸다가 과제가 직접 완료되었는지 확인해야한다는 것입니다. 앞으로 작업이 완료 될 시간은 통제 할 수 없습니다. CompleteFuture의 가장 큰 개선은 작업 완료 시간도 열려 있다는 것입니다.
Future.complete (60);
완료 시간을 설정하는 데 사용됩니다.
완전성의 비동기 실행 :
public static integer calc (Integer para) {try {// long execution stread.sleep (1000); } catch (InterruptedException e) {} para * para; } public static void main (string [] args)은 InterruptedException, executionException {Final ThemetableFuture <integer> future = completableFuture .SupplyAsync (() -> calc (50)); System.out.println (future.get ()); } 완전한 완료의 스트리밍 호출 : 공개 정적 정수 계산 (정수 para) {try {// long execution stread.sleep (1000); } catch (InterruptedException e) {} para * para; } public static void main (String [] args)은 InterruptedException, executionException {wemberatableFuture <void> fu = completableFuture .SupplyAsync (() -> calc (50)) .thenApply ((i) -> integer.toString (i)). .thenaccept (System.out :: println); fu.get (); }여러 완전한 충만을 결합하십시오.
공개 정적 정수 계산 (정수 파라) {return para / 2; } public static void main (string [] args)은 InterruptedException, executionException {wempletableFuture <void> fu = wompletableFuture .SupplyAsync (() -> calc (50)). thenComcope ((i) -> 완전한 future.supplySync (() -> calc (i))). "/" ") .thenaccept (System.out :: println); fu.get (); } 이 예제는 Java 8의 새로운 기능에 더 중점을 둡니다. 기능을 설명하기위한 몇 가지 예가 있습니다.
완전한 연도는 성능과 거의 관련이 없지만 기능 프로그래밍 및 기능 향상을 지원하는 데 더 중요합니다. 물론 완료 시간 설정은 하이라이트입니다.
3. StampedLock
이전 기사에서는 잠금 분리가 방금 언급되었으며 잠금 분리의 중요한 구현은 readwritelock입니다. StampedLock은 ReadWritelock의 개선입니다. StampedLock과 ReadWritelock의 차이점은 StampedLock이 읽기가 쓰기를 차단해서는 안된다고 믿고, StampedLock은 읽기와 쓰기가 상호 배타적 일 때 글쓰기 스레드가 쓰는 것을 허용하지 않고 다시 읽어야한다고 생각합니다. 이 디자인은 더 많이 읽고 덜 쓰면 스레드 굶주림을 쓰는 문제를 해결합니다.
따라서 StampedLock은 스레드를 작성하는 경향이있는 개선입니다.
StampedLock 예 :
import java.util.concurrent.locks.stampedlock; public class point {private double x, y; Private Final Final StampedLock SL = New StampedLock (); void Move (Double Deltax, Double Deltay) {// 독점적으로 잠긴 메소드 Long Stamp = sl.writelock (); {x += deltax를 시도하십시오. y += 델타; } 마침내 {sl.unlockwrite (Stamp); }} double distonefromorigin () {// 읽기 전용 메소드 long stamp = sl.gryoptimisticread (); 이중 currentx = x, currenty = y; if (! sl.validate (stamp)) {stamp = sl.readlock (); try {currentx = x; currenty = y; } 마침내 {sl.unlockread (Stamp); }} return math.sqrt (currentx * currentx + currenty * currenty); }}위의 코드는 쓰기 스레드와 읽기 스레드를 시뮬레이션합니다. StampedLock은 스탬프에 따라 상호 배타적인지 확인합니다. 스탬프를 한 번 쓸 때 특정 값이 증가합니다.
tryptimisticread ()
언급했듯이 독서와 쓰기가 상호 배타적이지 않은 상황입니다.
스레드를 읽을 때마다 먼저 판단을 내립니다.
if (! sl.validate (Stamp))
Validate에서는 먼저 쓰기 스레드 작성이 있는지 확인한 다음 입력 값이 현재 스탬프와 동일한 지 여부, 즉 읽기 스레드가 최신 데이터를 읽을 것인지 확인합니다.
쓰기 스레드 쓰기가 있거나 스탬프 값이 다른 경우 반환이 실패합니다.
판단이 실패하면 물론 반복적으로 읽을 수 있습니다. 예제 코드에서는 반복적으로 읽을 수는 없지만 대신 낙관론 잠금 장치를 사용하여 일반 읽기 잠금 장치로 퇴화시켜 읽습니다. 이 상황은 비관적 인 독서 방법입니다.
Stamp = sl.readlock ();
StampedLock 구현 아이디어 :
CLH 스핀 잠금 장치 : 잠금 응용 프로그램이 실패하면 읽기 스레드가 즉시 일시 중단되지 않습니다. 대기 스레드 큐가 잠금에 유지됩니다. 잠금에 적용되는 모든 스레드이지만이 큐에는 성공적인 스레드가 기록되지 않습니다. 각 노드 (하나의 노드는 스레드를 나타냅니다)는 잠긴 비트를 저장하여 현재 스레드가 잠금을 해제했는지 여부를 결정합니다. 스레드가 잠금을 얻으려고 할 때, 전류 대기 큐의 꼬리 노드를 전임 노드로 얻습니다. 그리고 다음과 같은 코드를 사용하여 프리앰블 노드가 잠금을 성공적으로 해제했는지 여부를 결정합니다.
while (pred.locked) {
}
이 루프는 이전 노드가 잠금을 해제 할 때까지 기다려서 현재 스레드가 운영 체제에 의해 매달리지 않아 성능이 향상됩니다.
물론, 끝없는 스핀은 없을 것이며, 여러 번의 스핀 후에 실이 매달릴 것입니다.