내가 틀렸다면 정정해 주세요.
낙관적 잠금의 구현 원리는 cas 연산이며, Java의 경량 잠금도 cas를 기반으로 구현됩니다.
비관적 잠금의 가장 큰 문제점은 차단입니다.
Java 가상 머신에 대한 심층적인 이해에서 경량 잠금은 일반적으로 중량 잠금(뮤텍스 잠금)보다 우수하다고 언급되어 있습니다. 동시성 잠금 경쟁이 치열할 경우 경량 잠금은 긴 회전을 소모합니다. CPU로 인해 경량 잠금 장치의 성능이 기존의 중량 잠금 장치보다 느려집니다. 그러면 낙관적 잠금에는 spin과 cas도 포함되므로 동시성이 높을 경우 낙관적 잠금은 좋은 솔루션이 아닌 것 같습니다.
그러나 일부 블로그 게시물에서는 높은 동시성에는 낙관적 잠금이 더 적합하다고 언급했습니다.
예를 들어 이 기사에서는 높은 동시성 데이터베이스 액세스를 위해 낙관적 잠금을 사용하는 것에 대해 언급했습니다.
http://blog.csdn.net/amqvje /아...
질문 1, 동시성이 높은 경우 어떻게 선택하나요?
질문 2 낙관적 잠금의 단점은 무엇입니까? 모두가 낙관적 잠금을 사용하지 않는 이유는 무엇입니까? 낙관적 잠금은 동시성이 높을 때 사용됩니다. 동시성이 높지 않으면 낙관적 잠금을 사용해도 문제가 되지 않습니다.
怪我咯2017-05-16 13:07:01
간단히 말하면, 일반적인 상황에서는 읽기만 하고 쓰지 않는 작업에는 낙관적 잠금이 적합하고, 읽기와 쓰기가 혼합된 작업에는 비관적 잠금이 적합합니다. 방문자 수를 늘리는 등 쓰기 작업이 매우 간단하고 짧은 경우 낙관적 잠금을 사용하거나 읽은 데이터가 최신인지 확인할 필요가 없는 경우에도 사용할 수 있습니다. 낙관적 잠금을 사용하는 것이 실제로 80%의 경우에 더 나은 선택입니다.
CAS는 원자 수준 작업을 구현하기 위해 하드웨어 CPU 명령 지원에 의존하므로 일반적으로 높은 동시성 조건에서 더 빠릅니다. 그러나 이 속도에는 읽기 및 쓰기가 있을 때 CPU 캐시 오류가 있다는 단점이 있습니다. 귀하의 CPU가 단일 코어(비인텔 플랫폼 내장)가 아닌 한 속도가 증가할 수 있습니다.
요컨대, 높은 동시성 성능을 향상시키기 위해서는 문제를 설명하기 위한 실제 측정 데이터가 여전히 필요합니다. 위에서 언급한 것은 모두 이론입니다. 도움이 되길 바랍니다.
阿神2017-05-16 13:07:01
비관적 잠금이든 낙관적 잠금이든 실제로는 동시성 제어에 대한 아이디어이며, 낙관적 잠금과 비관적 잠금의 구체적인 선택은 비즈니스 시나리오를 기반으로 합니다.
비관적 잠금:
일반적으로 우리가 사용하는 비관적 잠금은 데이터베이스 수준에서 배타적 잠금을 추가하는 것입니다. 잠금이 성공하면 트랜잭션 제출이 성공적으로 해제됩니다. 실패하면 데이터가 수정되고 있음을 의미합니다. mysql의 innodb를 사용하는 경우 mysql 자동 커밋 속성을 끄도록 주의하세요. 왜냐하면 mysql은 기본적으로 자동 커밋 모드를 사용하기 때문입니다. 즉, 업데이트 작업을 수행하면 MySQL이 즉시 결과를 제출하고 주의를 기울일 것입니다. 기본적으로 innodb는 행 수준 잠금을 사용하지만 행 수준 잠금은 인덱스를 기반으로 합니다. SQL이 인덱스를 사용하지 않으면 mysql은 테이블 수준 잠금을 사용하여 테이블을 잠급니다. set autocommit=0
장점 및 단점:
비관적 잠금은 "먼저 잠금을 얻은 다음 액세스"하는 보수적인 전략으로, 데이터 처리 보안을 보장합니다. 그러나 효율성 측면에서 잠금 메커니즘은 데이터베이스에 추가 오버헤드를 발생시키고 교착 상태 가능성을 높입니다. 또한 읽기 전용 트랜잭션 처리에서는 충돌이 발생하지 않으므로 잠금을 사용할 필요가 없으며 이는 시스템 부하만 증가시킵니다. 또한 트랜잭션이 특정 데이터 행을 잠그면 다른 트랜잭션은 해당 데이터 행을 처리하기 전에 트랜잭션이 처리될 때까지 기다려야 합니다.
낙관적 잠금은 실제로 데이터가 정상적인 상황에서 충돌을 일으키지 않는다고 가정하므로 업데이트를 위해 데이터가 제출되면 데이터 충돌이 공식적으로 감지되고 충돌이 발견되면 사용자가 반환됩니다. 오류 정보를 제공하고 사용자가 무엇을 할지 결정하도록 합니다.
일반적으로 코드 논리 계층에서 직접 작성할 수 있습니다. 비관적 잠금과 비교하여 낙관적 잠금은 데이터베이스에서 제공하는 잠금 메커니즘을 사용하지 않고 일반적으로 버전 번호나 타임스탬프를 사용하여 구현됩니다. 버전 번호를 사용하는 경우 데이터를 초기화할 때 버전 번호를 지정할 수 있으며, 데이터에 대한 각 업데이트 작업은 버전 번호에 대해 +1 작업을 수행합니다. 그리고 현재 버전 번호가 데이터의 최신 버전 번호인지 확인합니다. 예:
으아악
낙관적 잠금은 데이터 경쟁 가능성이 매우 작다고 생각하므로 최대한 직접적으로 진행하고 제출할 때까지 잠금을 설정하지 않으므로 잠금 및 교착 상태가 발생하지 않습니다. 그러나 이 작업을 간단하게 수행하면 여전히 예상치 못한 결과가 발생할 수 있습니다. 예를 들어 두 트랜잭션 모두 데이터베이스의 특정 행을 읽은 다음 수정 후 데이터베이스에 다시 쓰는 경우 문제가 발생합니다.
낙관적 잠금의 실패는 확률이 작은 이벤트이며 발생하려면 여러 조건의 협력이 필요합니다. 예:
사용자 A가 읽기를 완료한 후 사용자 B가 우연히 기록을 삭제했습니다. 그 후 사용자 C가 새 레코드를 삽입했습니다.
이때, 실수로 새로 삽입된 레코드의 ID가 사용자 A가 읽은 레코드의 ID와 일치하며, 두 버전 번호 모두 기본값이 0입니다.
사용자 C가 작업을 완료한 후 사용자 A는 완료된 기록을 수정하고 저장합니다. ID와 버전이 모두 일치하므로 사용자 A는 성공적으로 저장했습니다. 그러나 사용자 C가 삽입한 레코드를 덮어썼습니다.
현재 낙관적 잠금이 실패하는 근본적인 이유는 애플리케이션에서 사용하는 기본 키 ID 관리 전략이 낙관적 잠금과 어느 정도 호환되지 않는다는 것입니다.
PHPz2017-05-16 13:07:01
작업을 시작하기 전에도 질문자와 같은 생각이었습니다. 실제 작업에서는 둘 사이에 실제로 큰 차이가 없습니다. 실제 높은 동시성에서 시스템에서 가장 시간이 많이 걸리는 부분은 항상 네트워크 연결, 데이터베이스 쿼리 및 작업입니다. 스레드의 활성 절전 모드는 기본적으로 무시할 수 있습니다.
我想大声告诉你2017-05-16 13:07:01
핵심 질문은 사실이 비관적인가 아니면 낙관적인가?입니다.
리소스 경쟁이 치열하고 공유할 수 없는 경우 낙관적 잠금은 수많은 요청에 대한 희망을 무산시킬 것입니다.
리소스에 대한 경쟁이 없는 경우(동시성 수준과 반드시 관련이 있는 것은 아니지만 비즈니스에 더 큰 영향을 미침) 비관적 잠금은 불필요한 잠금을 의미합니다. 리소스가 원래 공유 가능한 경우(예: 리소스가 여러 읽기 전용 당사자를 지원하는 경우) 비관적 잠금은 원래 사용 가능한 시간을 잃는 것을 의미합니다.
Java Virtual Machine에 대한 심층적인 이해에서는 일반적으로 경량 잠금이 중량 잠금(뮤텍스 잠금)보다 낫다고 언급되어 있습니다. 동시성 잠금 경쟁이 치열할 경우 경량 잠금이 오랫동안 잠길 것입니다. 시간 회전은 CPU를 소비하므로 경량 잠금의 성능은 기존의 중량 잠금보다 느려집니다. 그렇다면 낙관적 잠금에는 spin과 cas도 포함되므로 동시성이 높은 비관적 잠금은 좋은 해결책이 아닌 것 같습니다.
저는 JVM에 대해 잘 모릅니다. 그런데 "낙관적 잠금에도 Spin과 Cas가 존재한다"는 것은 무슨 뜻일까요? cas는 스핀 잠금의 구현 방법입니다. 왜 병렬화해야 합니까? "또한"은(는) 무슨 뜻인가요? 비관적 잠금은 차단 작업이고 회전이 없으며 지속적으로 CPU를 소모하지 않습니다.