경쟁 조건과 임계 구역 문서의 검증 코드다. if __name__ == "__main__": 아래가 자체 테스트다.

"""경쟁 조건: 두 프로세스가 공유 변수 x에 1을 더한다. x = x + 1은 기계어로
읽기(load) -> 더하기(add) -> 쓰기(store) 세 단계다. 두 프로세스의 단계를 섞을 수 있는
모든 순서를 다 해 보고, 결과가 실행 순서에 따라 달라지는지 확인한다."""
from itertools import combinations


def interleavings(n_a, n_b):
    """A의 단계 n_a개와 B의 단계 n_b개를 각자의 순서는 지키며 섞는 모든 방법."""
    total = n_a + n_b
    for pos in combinations(range(total), n_a):
        seq, ia, ib = [], 0, 0
        for k in range(total):
            if k in pos:
                seq.append(("A", ia)); ia += 1
            else:
                seq.append(("B", ib)); ib += 1
        yield seq


def run(seq, x0=0):
    x = x0
    reg = {"A": None, "B": None}          # 프로세스마다 자기 레지스터
    for who, step in seq:
        if step == 0:
            reg[who] = x                  # load
        elif step == 1:
            reg[who] += 1                 # add
        else:
            x = reg[who]                  # store
    return x


if __name__ == "__main__":
    results = {}
    for seq in interleavings(3, 3):
        results.setdefault(run(seq), []).append(seq)
    print({k: len(v) for k, v in results.items()})
    # 섞는 방법은 C(6,3) = 20가지, 결과는 2(맞음)와 1(갱신 하나가 사라짐) 두 가지
    assert sum(len(v) for v in results.values()) == 20
    assert set(results) == {1, 2}
    # 결과가 2인 것은 한쪽이 세 단계를 다 끝낸 뒤 다른 쪽이 시작한 두 경우뿐
    assert len(results[2]) == 2
    # 카드 C3: A load, B load, A add, A store, B add, B store -> 1
    assert run([("A", 0), ("B", 0), ("A", 1), ("A", 2), ("B", 1), ("B", 2)]) == 1
    print("ALL CHECKS PASSED")