자바 동시성 : CAS 대 잠금
Book Java Concurrency in Practice를 읽고 있습니다. 15 장에서는 비 차단 알고리즘과 CAS ( 비교 및 교환 ) 방법에 대해 설명합니다.
CAS가 잠금 방법보다 훨씬 더 나은 성능을 발휘한다고 기록되어 있습니다. 이 두 개념을 이미 작업 한 사람들에게 물어보고 싶고,이 두 개념 중 어느 것을 선호하는지 듣고 싶습니다. 정말 훨씬 빠르나요?
나에게 잠금 사용은 훨씬 더 명확하고 이해하기 쉽고 유지 관리가 더 좋을 수도 있습니다 (내가 틀렸다면 수정하십시오) . 더 나은 성능 향상을 위해 잠금보다 CAS와 관련된 동시 코드를 만드는 데 정말로 집중해야합니까, 아니면 지속 가능성이 더 중요합니까?
무엇을 사용할 때 엄격한 규칙이 없을 수도 있다는 것을 알고 있습니다. 하지만 CAS의 새로운 개념에 대한 의견과 경험을 듣고 싶습니다.
CAS는 일반적으로 잠금보다 훨씬 빠르지 만 경합 정도에 따라 다릅니다. 읽기와 비교 사이에 값이 변경되면 CAS가 재 시도를 강제 할 수 있기 때문에 해당 변수가 다른 많은 스레드에 의해 강하게 타격을받는 경우 (또는 새 값을 계산하는 데 비용이 많이 드는 경우) 스레드는 이론적으로 바쁜 대기 상태에 빠질 수 있습니다. 이전 값 (또는 둘 다)에서).
CAS의 주요 문제는 잠금보다 올바르게 프로그래밍하는 것이 훨씬 더 어렵다는 것입니다. 잠금은 메시지 전달 또는 STM 보다 올바르게 사용하기가 훨씬 더 어렵 기 때문에 잠금 사용에 대한 링잉 보증으로 받아들이지 마십시오.
작업의 상대 속도는 대체로 문제가되지 않습니다. 관련된 것은 잠금 기반 알고리즘과 비 차단 알고리즘 간의 확장 성 차이입니다. 그리고 만약 1 개 또는 2 개 코어 시스템에서 실행 중이라면 그런 것에 대해 생각하지 마십시오.
비 블로킹 알고리즘은 잠금 기반 알고리즘보다 "중요 섹션"이 짧기 때문에 일반적으로 확장 성이 더 좋습니다.
a ConcurrentLinkedQueue
와 a 사이의 숫자를 볼 수 있습니다 BlockingQueue
. 여러분이 보게 될 것은 CAS 가 보통 (실제 응용 프로그램에서는 더 현실적) 스레드 경합에서 눈에 띄게 더 빠르다는 것입니다.
비 차단 알고리즘 의 가장 매력적인 속성은 한 스레드가 실패하면 (캐시 미스 또는 더 나쁜 경우에는 세그 오류) 다른 스레드가이 실패를 인식하지 못하고 계속 진행할 수 있다는 사실입니다. 그러나 잠금을 획득 할 때 잠금 보유 스레드에 일종의 OS 오류가있는 경우 잠금이 해제되기를 기다리는 다른 모든 스레드도 오류와 충돌합니다.
귀하의 질문에 답하기 위해, 예, 비 차단 스레드로부터 안전한 알고리즘 또는 컬렉션 ( ConcurrentLinkedQueue
, ConcurrentSkipListMap/Set
)은 블로킹 대응 알고리즘 보다 훨씬 빠를 수 있습니다. Marcelo가 지적했듯이 nonblocking 알고리즘을 올바르게 얻는 것은 매우 어렵고 많은 고려가 필요합니다.
Michael 및 Scott Queue 에 대해 읽어야합니다 . 이것은 큐 구현이며 ConcurrentLinkedQueue
단일 CAS를 사용하여 양방향 스레드로부터 안전한 원자 함수를 처리하는 방법을 설명합니다 .
잠금없는 동시성 주제와 밀접하게 관련된 좋은 책이 있습니다. Maurice Herlihy의 "다중 프로세서 프로그래밍 기술"
실제 비교를 찾고 있다면 여기에 하나가 있습니다. 우리의 애플리케이션에는 2 개의 스레드가 있습니다. 1) 네트워크 패킷 캡처를위한 리더 스레드와 2) 패킷을 받아 계수하고 통계를보고하는 소비자 스레드입니다.
스레드 # 1은 스레드 # 2와 한 번에 하나의 패킷을 교환합니다.
결과 # 1- 클래스 이름이 CASSynchronousQueue 인 SynchronousQueue 와 동일한 원칙을 사용하는 사용자 지정 CAS 기반 교환을 사용합니다 .
30,766,538 packets in 59.999 seconds :: 500.763Kpps, 1.115Gbps 0 drops
libpcap statistics: recv=61,251,128, drop=0(0.0%), ifdrop=0
결과 # 2 -CAS 구현을 표준 Java SynchronousQueue로 대체 할 때 :
8,782,647 packets in 59.999 seconds :: 142.950Kpps, 324.957Mbps 0 drops
libpcap statistics: recv=69,955,666, drop=52,369,516(74.9%), ifdrop=0
성능의 차이가 더 이상 명확하지 않다고 생각합니다.
참고 URL : https://stackoverflow.com/questions/2664172/java-concurrency-cas-vs-locking
'program tip' 카테고리의 다른 글
데이터 목록 레이블을 표시하지만 실제 값을 제출합니다. (0) | 2020.11.05 |
---|---|
Qt Creator 색 구성표 (0) | 2020.11.05 |
보다 전문화 된 인터페이스로 다시 캐스팅 (0) | 2020.11.05 |
w3wp.exe 란 무엇입니까? (0) | 2020.11.05 |
php artisan migrate : make create_mytable 실패 : "migrate : make"가 정의되지 않았습니다. (0) | 2020.11.04 |