정말 오랜만에 블로그 글을 작성한다.
남에게 공개하기엔 정제되지 않은 글이 많아서였을 거다.
최근에 동기, 비동기, 블로킹, 논블로킹에 대해 정리해 볼 기회가 생겼다.
POSIX 정의(IEEE 1003.1-2008) 도 찾아보고,
Java Concurrency In Practice라는 책도 찾아보고,
토비의 스프링의 저자, 토비의 강연 동영상도 찾아봤다.
학습하다 보니 기존에 알던 바와는 조금 달랐다.
누군가에게 도움되기를 바라며 학습한 내용을 정리해본다.
먼저 이 글은 동기와 비동기를 다룬다.
동기: 결과에 신경쓰는 것
비동기: 결과에 신경쓰지 않는 것
이런 의미로 많이 사용하고, 나도 그랬다.
코끼리는 코가 길다.
하지만 코가 길다고 코끼리라고 할 수는 없다.
위 정의는 동기, 비동기의 본래 의미와는 많이 다르다.
이건 정의가 아니라 특성이나 관찰에 가깝다.
이제 동기와 비동기를 다시 정의해보자.
동기, 같은 시각이라는 뜻이다.
그리스어에서 따온 단어다.
Syn: with, together
chrono: time
-ous: 형용사 접미사
이 용어는 정확한 정의나 표준이 없다.
이럴 땐 단어 자체에 입각해 정의내리는 편이 나을 것이라고 낫다고 생각했다.
누군가에게 다시 설명해야 하기 때문이다.
단어와 동떨어진 본인만의 정의로 누굴 설득할 수 있겠는가?
그 이름에 걸맞게 작업들이 같은 시간에 이루어짐을 의미한다.
살짝 다르게 이야기 하면, 작업들의 시작과 끝이 일치함.
풀어서 이야기 하면, (어떤 시각 x의) 작업들이 함께 시작해 함께 끝남.
왜 작업들이 함께 시작해, 함께 끝나게 할까?
예시들로 알아보자.
함께 시작해 함께 끝나게 한다는 건, 반대로 말하면 함께 시작하지 않은 작업은 배척한다는 것이다.
송금 기능 sendMoney()
를 만든다고 생각해보자.
송금에는 송금자 계좌번호
, 송금자 비밀번호
, 송금 대상
이 필요하다.
각각을 알기 위한 송금 준비 함수 ready()
가 있고, 그 하위 작업들이 있다.
ready()
getSender()
: 송금자 계좌번호, 비밀번호 알아오기 + 검증getReceiver()
: 송금 대상 알아오기 + 검증ready()
가 완료되기 전에, sendMoney()
를 수행한다면 올바르게 수행될 수 없다.
따라서, 동기를 통해 의도적으로 이를 보장해주어야 한다.
동시에 여러 작업을 수행해야 할 때도 있다.
(예시는 아직 작성중..)
Java에는 synchronized
키워드가 있으며, 블럭이나 함수에 적용시킬 수 있다.
synchronized
를 사용하면 해당 블럭에는 한 스레드만 진입이 가능하다.
'작업 중에 다른 작업이 끼어들지 못하게 한다' 목적을 위해 사용한다.
블로킹-논블로킹은 CPU 사용권의 분배 방법,
동기-비동기는 작업들의 수행 방법이다.
프로세스는 메모리에 올라간 프로그램이다.
프로세스는 작업들로 이뤄지고, CPU가 실행한다.
즉, CPU가 작업을 수행하기 때문에 둘은 같이 쓰일 수 밖에 없다.
그래서 헷갈린다.
동기와 블로킹은 하나의 목적을 위해 같이 쓰이는 경우가 많다.
(프로그래밍 언어를 예로 들면, 순차 실행을 위해 사용할 수 있다)
하지만 자세히 살펴보면 둘의 목적은 조금 다르다.
다음과 같이 생각하곤 하는데:
"코드의 순차 실행을 위해 동기를 사용했어"
"코드의 순차 실행을 위해 블로킹을 사용했어"
"?? 같은거 아니야?"
위 사고과정을 좀 더 자세히 정정해보면:
"동기는 작업 중 끼어들기를 막기 위해 사용했어"
"블로킹은 호출한 작업이 기존 작업을 멈추게 하기 위해 사용했어"
"둘이 합쳐 순차 실행이라는 목적을 달성했네"
이제 좀 구분이 되는 것 같다.
이해를 위해 예시를 추가하고 싶거나, 틀렸다고 생각하시는 부분이 있다면
자유롭게 의견주시면 감사하겠습니다.
동기