찾다

 >  Q&A  >  본문

java - AQS中源码疑问

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

protected final void setState(int newState) {
    state = newState;
}
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操作能保证线程安全呢?还是我的理解有问题呢?谢谢各位大牛了!

巴扎黑巴扎黑2802일 전628

모든 응답(3)나는 대답할 것이다

  • 高洛峰

    高洛峰2017-04-18 10:50:23

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

    회신하다
    0
  • ringa_lee

    ringa_lee2017-04-18 10:50:23

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

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

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

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

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

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

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

    회신하다
    0
  • 天蓬老师

    天蓬老师2017-04-18 10:50:23

    요약:

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

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

    회신하다
    0
  • 취소회신하다