원자성 다선정

우리가 무상태 대상에 상태를 추가할 때 어떤 상황이 나타날지 가정해 보자. 우리가 요청 수량의 통계를 늘리고 싶다고 가정하면 흔히 볼 수 있는 방법은 대상에long 유형의 영역을 추가하고 요청을 처리하지 않으면 이 값을 추가하는 것이다.
package com.zy.test;

public class StatelessDemo {
    
    private long count = 0;
    
    public void service() {
        count++;
        System.out.println("      " + count);
    }
    
    
    public static void main(String[] args) {
        StatelessDemo statelessDemo = new StatelessDemo();
        RequestDemo requestDemo = new RequestDemo(statelessDemo);
        for (int i = 0; i < 20; i++) {
            Thread thread = new Thread(requestDemo);
            thread.start();
        }
    }

}

class RequestDemo implements Runnable {
    StatelessDemo statelessDemo;
    RequestDemo(StatelessDemo statelessDemo) {
        this.statelessDemo = statelessDemo;
    }

    @Override
    public void run() {
        statelessDemo.service();
    }
    
}


결과:
      1
      2
      3
      4
      5
      6
      7
      9
      10
      9
      12
      13
      12
      14
      15
      16
      17
      18
      19
      20

유감스럽게도, 인쇄 결과를 보면, 프로그램은 우리가 예상한 대로 실행되지 않았고, 중간에 몇 번의 방문 수가 뜻밖에도 같았다.물론 방법 서비스는 정상적인 단일 라인에서 운행하는 데 아무런 문제가 없다.문제는 점증 조작count++에서 비롯된다. 문법이 치밀하게 보면 한 줄이지만 이 조작은 원자적인 조작이 아니기 때문에 분할할 수 없는 조작으로 실행되지 않는다. 실제로 이것은 세 가지 독립된 조작을 포함한다. 그것이 바로count의 값을 읽고 1을 더한 다음에 계산 결과를count에 쓰는 것이다.이것은 읽기 + 수정 + 쓰기 작업의 순서이며, 그 결과 상태는 이전의 상태에 의존한다.결과에서 7이 나오고 9, 10.그것은 아마도 이럴 것이다. 여덟 번째 요청과 아홉 번째 요청이 왔을 때 여덟 번째 요청은 먼저count에 1을 더한 다음에 결과 8을count에 쓴다. 이때 방법이 아직 실행되지 않았다. 인쇄 작업을 수행하려고 할 때 아홉 번째 요청이 왔다. 그리고count 더하기 1을 빨리 실행했고 더하기 1의 결과인 9을count에 썼다. 그러나 아직 인쇄 작업을 실행하지 않았다. 이때여덟 번째 요청이 인쇄를 실행했다(결과는 9). 아홉 번째 요청이 인쇄를 실행하려고 할 때 열 번째 작업이 왔다. 플러스 1을 실행하고 업데이트를 하면 아홉 번째 요청이 인쇄를 실행할 차례이다(결과는 10).이제야 상술한 결과가 나왔다.이 모든 것은count++ 작업이 원자성이 아니라, 이러한 작업을 수행하는 시차적인 실행이 부적절하여 이러한 결과가 나타나는 데 있다.이런 상황을 정적 조건이라고 부른다.
다음 절에서는 정적 조건을 중점적으로 소개한다.

좋은 웹페이지 즐겨찾기