구체적인 예
실제 예제를 추가하고이를 소프트웨어 엔지니어링 세계에 연결하고 싶습니다. 먼저, 어떤 상황에서는 "동기 성"에 대한 직관적 인 정의 : 반딧불이 번쩍이는 것과 일치하기를 바랍니다 . 둘째, 4x100 여자 올림픽 중계 경주를 고려하십시오 . 셋째, 군사 영화의 오래된 병력을 생각해보십시오. "남성, 시계를 동기화하십시오!"
이제 무슨 일이 일어나고 있는지 생각해 봅시다. 이 모든 것들이 프로세스 이거나 시간이 연장 된 엔터티 임을 관찰하여 시작하자 . 그릇이 "동기"이고 바위가 "비동기"라고 말하는 것은 이치에 맞지 않습니다. 둘째, 탱고에 2가 걸립니다 . 당신은 "주자는 동기화"라고 말할 수 없습니다. 무엇과 동기화 하시겠습니까? 마지막으로, 두 프로세스가 동시에 동일한 주파수와 위상을 가지지 않는 한 동시에 어떤 작업을 수행 하려면 둘 중 하나 또는 둘 다 기다려야 합니다.
분석
사전 정의에 동기화 된 두 엔티티가 "동시에 발생하거나 동시에 존재"할 때, 이는 반딧불에서 나오는 빛의 개념과 매우 잘 어울립니다. 불행히도, 빛이 "동기화되었다"고 말하는 것은 반딧불 조명 프로세스 가 동기화 되었다는 것을 말끔하게 말하는 것입니다 .
그렇다면 어떻게 애플 스마트 워치와 NTP가없는 반딧불 무리가 후단을 동시에 번쩍이게 할 수 있을까? 일관된 템포를 설정하고 약간 조정할 수 있다면 아주 쉽습니다. 그들은 단지 번쩍이고, 더 많은 사람들이 바로 뒤에서 번쩍이면 속도가 느려지고 (지연이 증가), 바로 앞에 더 많은 번 플래시가 있으면 속도가 증가합니다 (지연이 감소합니다). 따라서 간단한 피드백 프로세스를 사용하여 본질적으로 동일한 템포 및 위상에 도달 할 수 있습니다. 여기서 중요한 관찰은 이들이 올바른 순간이 깜빡 일 때까지 기다림 으로써 동기를 달성한다는 것 입니다.
4x100 레이스는 두 가지 형식의 프로세스 타이밍이 실제로 작동 하기 때문에 흥미 롭습니다 . 팀 내의 러너 는 동기화 되고 다른 팀 의 러너 는 "비동기 적"입니다. 릴레이의 두 번째 러너는 첫 번째 러너 가 전송 영역에 들어갈 때까지 기다려야 합니다 . 핸드 오프는 두 주자 사이의 동기 이벤트입니다. 그러나 다른 차선의 주자는 다른 차선 에서 일어나는 일을 신경 쓰지 않으며 , 가장 느리게 진행하지 않고 핸드 오프를 동기화합니다. 각 러너 레인은 서로에 대해 비동기 적입니다. 다시 말하지만, 비동기는 대기하지 않지만 동기화는 대기를 수반합니다.
마지막으로 회사의 병사 (소대, 소방대 등)는 적을 동시에 공격 할 수 있도록 시계를 동기화해야합니다 . 일부 군인은 다른 군인보다 먼저 자신의 위치에 도착하거나 적에게 더 빨리 발포 할 수 있습니다. 그러나 동시 공격은 일반적으로 놀람 요소 때문에 우연한 공격보다 효과적입니다. 그래서 동시성을 달성하기 위해, 많은 군인이 있어야 기다릴 행동 정해진 시간.
기능 정의
이것이 왜 대기에 중점을 두는가? 대기는 비동기식 프로세스와 동기식 프로세스를 구별하는 정의 기능이기 때문입니다. 알지 못하는 두 개의 프로세스가있는 경우 기본적으로 프로세스가 비동기라고 가정해야합니다. 예를 들어, 패키지 배달과 구급차 운전은 대부분 동기화 되지 않습니다 . 실제로 두 프로세스가 동기화되었음을 증명하려면 매우 특별한 시점 인 동기화 지점 을 찾아야합니다 .
배달원이 패키지를 내려 놓고 구급차가 누군가를 병원으로 몰아 넣는 것은 일반적으로 "동기화 지점"으로 식별되는 시점을 공유하지 않습니다. 반면에, 반딧불이 번쩍이면 반동 할 때마다 동기 점이 있고, 릴레이 주자는 배턴을 내릴 때마다 동조 점이 있으며, 군인은 공격을 시작할 때 동기 점이 있습니다. 하나 이상의 동기 점을 식별 할 수 있으면 프로세스가 동기화 됩니다. "syn-"은 "with"또는 "together"를 의미 하는 그리스어 접두어 이고 "chrono"는 "시간" 의 그리스어 루트 이므로 이해하기 쉬워야합니다 . "동기화"는 문자 그대로 "동시"를 의미합니다.
경계
"동기화"가 반드시 하나 또는 두 프로세스 의 전체 수명 에 적용되는 것은 아닙니다 . 나는 그것이 "동기화 시점까지의 대기 시간"에만 적용된다고 주장한다. 따라서 두 프로세스는 통신이 필요한 상태에 도달 할 때까지 비동기식으로 작동 한 다음 동기화되어 정보를 교환 한 후 비동기식으로 계속 될 수 있습니다. 간단한 예는 커피를 마시는 사람을 만나는 것입니다. 분명히 회의는 동기화 지점 (또는 많은 것)이며 두 사람이 해당 지점에 도착한다는 사실은 동기화를 보여줍니다. 그러나 우리는 두 사람이 커피를 마시기 때문에이 두 사람의 생애를"동기화"됩니다. 그것은 그들의 삶에서 그들이 만난 유일한 순간 일 수도 있고, 그들이하는 모든 일은 그렇지 않으면 독립적입니다.
우연한 만남이 시연을 보여주는 경우도 아니다. 두 낯선 사람이 길거리에서 서로를 지나가더라도 특정 시간에 특정 장소에 있다는 사실은 동기를 증명하지 못합니다. 한 사람이 버스를 기다리는 벤치에 앉아 있고 다른 사람이 걸어 다니는 것도 아닙니다. 프로세스가 목적 을 충족 할 때만 프로세스가 동기화됩니다 .
소프트웨어 연결
이제 소프트웨어에서 매우 기본적인 작업 인 파일에서 읽기를 생각해 봅시다. 아시다시피 대용량 저장소는 일반적으로 캐시 또는 주 메모리보다 수천에서 수백만 배 느립니다. 이러한 이유로 운영 체제 및 프로그래밍 언어 라이브러리는 일반적으로 동기 및 비동기 I / O 작업을 모두 제공합니다. 이제 프로그램에 단일 스레드 만있는 경우에도이 논의를 위해 OS를 "별도의 프로세스"로 생각해야합니다.
동조
"동기 I / O 읽기"를 수행 할 때 스레드는 데이터가 사용 가능할 때 까지 기다려야 합니다 . 이것은 배턴을 다음 주자에게 건네주는 릴레이 주자와 매우 비슷하지만, 두 주자가 트랙을 완전히 지나가는 릴레이를 상상해보십시오.
이 경우 프로그램 스레드와 OS I / O 프로세스가 "동시에 발생 (작동)"하지 않으므로 이러한 프로세스가 "동기화"되었다고 말하는 것이 이상해 보입니다. 그러나 그것은 그것을 보는 잘못된 방법입니다! "중계 팀의 선수는 동시에 달리지 않기 때문에 동기화되지 않습니다." 사실, 두 진술 모두 잘못되었습니다! 릴레이 팀의 주자가 수행 하고 있어야 동시에 실행,하지만 매우 구체적인 순간 : 바톤의 핸드 오프를. 실제로, 레이스 기간 동안 릴레이 팀이 동기화되도록 시작하는 것은이 특별한 순간입니다! I / O 요청 및 응답을 "배턴"으로 보는 경우,
반면에 슈퍼 컴퓨터에서 유한 요소 해석 (Finite Element Analysis)과 같은 것을 생각해 보면 수천 개의 프로세스가 대규모 글로벌 상태를 업데이트하기 위해 잠금 단계에서 작동해야한다는 것을 알 수 있습니다. 일부 노드가 다른 노드보다 주어진 시간 단계 동안 작업을 완료하더라도 결과는 공간을 통해 이웃에게 전파되므로 시간 단계가 완료 될 때까지 기다려야합니다. 이런 종류의 동기화는 반딧불과 같습니다. 모든 행위자는 같은 종류의 작업을 수행합니다.
공정 다양성
이러한 이유로, 우리는 "동종 동기", "이종 동기"및 "순차 동기"의 세 가지 종류의 일이 진행되고 있음을 알 수 있도록 몇 가지 용어를 발명 할 수 있습니다. 따라서 배우들이 동일한 작업을 동시에 수행 할 때 (FEA, 반딧불), 그들은 "동 질적"입니다. 서로 다른 작업을 동시에 수행 할 때 (게임에서 대상을 크롤링하거나 수영하는 대상, 게임에서 물리, 사운드, 인공 지능 스레드) 실행하는 "이종"입니다. 한 번에 하나씩 작업을 수행 할 때 "순차적"(릴레이 러너, I / O 차단)입니다. 그것들은 매우 다르게 보일지 모르지만, 하나의 필수 속성을 공유합니다. 모든 유형의 액터가 모든 사람들이 동시에 동기화 지점에 도착할 수 있도록 약간의 대기를 수행합니다. 동기화 포인트들 사이에서, 또는 "동일한 동작을 수행하는"은 동기의 속성과 관련이 없다.
GPU의 렌더 파이프 라인은 모두 프레임을 함께 마무리하고 새 프레임을 함께 시작해야하기 때문에 동기식입니다. 그들은 같은 종류의 일을하고 있기 때문에 동 질적이며 모두 함께 활동합니다. 그러나 서버의 주요 게임 루프와 원격 입력을 처리하는 블로킹 I / O 스레드는 매우 다른 종류의 작업을 수행하기 때문에 이기종이며 일부 I / O 스레드는 전혀 작동하지 않습니다. 연결이 사용됩니다. 그럼에도 불구하고, 그들은 원자 적으로 상태를 공유해야하기 때문에 동기화됩니다 (플레이어는 부분적인 게임 월드 업데이트를 보거나 서버가 플레이어 입력의 일부만을 보지 않아야합니다).
비동기
이제 "비동기 I / O 읽기"를 고려해 보자. 프로그램이 스토리지에서 약간의 데이터를 읽기 위해 OS로 요청을 보내면 호출 이 즉시 리턴 됩니다. 콜백을 무시하고 폴링에 집중합시다. 일반적으로 프로그램에서 데이터를 사용할 수있는 순간은 프로그램 스레드에 관한 한 특정 시점과 일치하지 않습니다. 프로그램이 명시 적으로 데이터를 기다리지 않으면 스레드는 그 순간이 언제 발생하는지 정확하게 알지 못합니다. 다음에 검사 할 때 데이터가 대기 중임을 발견합니다.
OS와 프로그램 스레드가 데이터를 넘겨 주기로 동의 한 특별한 회의 시간은 없습니다. 그들은 밤에 지나가는 두 배와 같습니다. 비동기 성은 이러한 대기가없는 것이 특징 입니다. 물론 프로그램 스레드는 결국 I / O 작업을 기다리게되지만 반드시 그럴 필요는 없습니다. I / O 페치가 발생하는 동안 다른 계산을 계속 수행 할 수 있으며 여유 시간이있을 때만 나중에 확인할 수 있습니다. 물론 OS가 데이터 가져 오기를 완료하면 대기하지 않습니다. 그것은 단지 어딘가에 편리하게 데이터를 넣고 비즈니스에 관한 것입니다. 이 경우, 프로그램이 배턴을 OS에 전달하고 OS가 나중에 돌아와서 데이터와 함께 배턴을 땅에 떨어 뜨리고 트랙에서 걸어 나가는 것과 같습니다. 프로그램이 핸드 오프를 받기 위해 대기 중이거나 대기 중이 아닐 수 있습니다.
병행
소프트웨어에서 함수를 "비동기"로 표시 할 때 종종 병렬 처리 를 원합니다 . 그러나 병렬 처리가 동기화를 의미하지는 않습니다 . 반딧불은 동기 및 비동기 동작을 모두 나타 내기 때문에 좋은 예입니다. 대부분의 파리가 일제히 번쩍이는 동안, 많은 그룹은 나머지 그룹과 분명히 일치하지 않았으며 더 무작위로 번쩍였습니다. 파리는 동시에 행동 했을지도 모르지만 모두 동기화 된 것은 아닙니다 .
이제 일부 코드를 "비동기"로 표시하면 표시되지 않은 나머지 코드가 "동기화"임을 의미하기 때문에 재미있어 보입니다. 그게 무슨 뜻입니까? "동기화"에 탱고에 2 개가 필요하다고 주장하지 않았습니까? 그러나 단일 스레드에서 실행되는 코드에 대해 이야기한다면 어떻게 될까요? 이 경우, 한 걸음 물러나서 프로그램을 상태 시퀀스와 해당 상태 간의 전환으로 생각해야합니다. 프로그램의 명령문은 상태 전이를 유발합니다. 우리는 그것을 진술로 시작하고 멈추는 "마이크로 프로세스"라고 생각할 수 있습니다. 언어에 의해 정의 된 시퀀스 포인트는 실제로 이러한 "마이크로 프로세스" 의 동기화 포인트 입니다. 따라서 단일 스레드를 볼 수 있습니다.
프로그래밍 언어의 무결성으로 인해 상태 업데이트가 여러 문을 방해하지 않으며 시퀀스 포인트는 컴파일러가 관찰 가능한 최적화를 할 수없는 경계를 정의합니다. 예를 들어, 명령문 내에서 표현식의 평가 순서는 정의되지 않았거나 지정되지 않아서 컴파일러가 다양한 방식으로 명령문을 최적화 할 수있는 자유를줍니다. 그러나 다음 문장이 시작될 때까지 PL 자체가 건전하다면 프로그램은 잘 정의 된 상태에 있어야합니다.
지금까지 "비동기"의 의미가 분명해야합니다. 이는 코드 블록 내에서 묵시적 동기 계약이 비동기 블록에 대해 제외됨을 의미합니다. 순차적 인 (일관되고 동기적인) 계산 모델에 의해 일반적으로 암시되는 안전성을 보장하지 않고 프로그램 상태를 독립적으로 업데이트 할 수 있습니다. 물론 이것은 불일치로 프로그램 상태를 파괴하지 않도록 특별한주의를 기울여야한다는 것을 의미합니다. 이것은 일반적으로 비동기 블록과 조정하기 위해 제한된 명시 적 동기화를 도입한다는 것을 의미합니다 . 이것은 비동기 블록이 서로 다른 시간에 비동기 및 동기 가 될 수 있음을 의미합니다 ! 그러나 동기화가 단지 동기 점의 존재를 나타내는 것임을 기억하면, 우리는이 개념을 받아들이는 데 어려움이 없을 것입니다.