java - AQS中源码疑问
巴扎黑
巴扎黑 2017-04-18 10:48:23
0
3
569

AbstractQueuedSynchronizer类中维护了一个用volatile修饰的state状态,而这个状态有如下的两种修改方法:

  • stateset方法:

protected final void setState(int newState) {
    state = newState;
}
  • CAS方法:

protected final boolean compareAndSetState(int expect, int update) {
    // See below for intrinsics setup to support this
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

那么,我的疑问来了,不是说volatile修饰的变量在多线程的单操作中,能够保证其写后读的可见性,即能保证线程安全,为什么还提供了CAS操作能保证线程安全呢?还是我的理解有问题呢?谢谢各位大牛了!

巴扎黑
巴扎黑

모든 응답(3)
小葫芦

이는 충돌이 아닙니다. setState는 단지 쓰기 작업이며 원래 상태에 관심이 없습니다. 예를 들어 상태는 원래 0이었습니다. 스레드 1과 스레드 2는 각각 값을 1로 설정했습니다. 그런 다음 스레드 2는 이를 2로 설정할 계획이며 이는 성공할 수 있습니다. 상태가 이미 1이고 스레드 2도 이를 알고 있지만 스레드 2는 이를 2로 설정하기만 하면 됩니다. 다음 방법은 작동하지 않습니다.

左手右手慢动作

네, 이해에 문제가 있습니다.

휘발성 수정 변수가 멀티 스레드 단일 작업에서 쓰기 후 읽기의 가시성을 보장할 수 있다는 의미, 즉 스레드 안전성이 보장된다는 의미는 아닙니다

가시성을 보장할 수 있다고 해서 스레드 안전성이 보장되는 것은 아닙니다. 가시성과 스레드 안전성은 동일한 개념이 아닙니다.

카스 작업은 여러 개의 작은 작업으로 나눌 수 있습니다

  1. 기대 변수와 상태 변수의 현재 값을 비교합니다. 동일하면 2단계로 진행하고, 다르면 메서드가 종료됩니다.

  2. 상태 업데이트에 값 할당

이 두 작업이 여러 스레드에서 동시에 호출되면 스레드 안전 문제가 발생합니다.
여기서 cas 메소드는 원자적 연산인 CPU의 cas 명령을 사용합니다. 동시성 문제를 피할 수 있습니다.

Peter_Zhu

요약:

  1. 원래 값에 의존하지 않는다면 set을 사용해도 됩니다

  2. 원래 값에 의존하는 경우 CAS를 사용하여 설정할 수 있습니다. 이것은 그 자체로 낙관적인 잠금입니다.

최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!