i) 동기적 콜백함수
function printImmediately(print) {
print();
}
printImmediately(() => console.log("hi"));
ii) 비동기적 콜백함수
function printWithDelay(print, timeout) {
setTimeout(print, timeout);
}
printWithDelay(() => console.log("async callback"), 2000);
콜백함수가 계속 중첩되면 코드의 가독성이 떨어지며 디버깅이 어려워짐. => 콜백지옥
promise: 비동기적 실행을 위한 자바스크립트 객체
✔️ Promise state
✔️ Promise APIs
Producer | Consumer
-Producer
const promise = new Promise((resolve, reject) => {
// heavy work ex) network, read files
console.log("doing something...");
setTimeout(() => {
resolve("sol");
reject(new Error("no network"));
}, 2000);
});
-Consumer
promise
.then((value) => {
console.log(value);
})
.catch((error) => {
console.log(error);
})
.finally(() => {
console.log("finally");
});
const fetchNumber = new Promise((resolve, reject) => {
setTimeout(() => resolve(1), 1000);
});
fetchNumber
.then((num) => num * 2)
.then((num) => num * 3)
.then((num) => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num - 1), 1000);
});
})
.then((num) => console.log(num));
async-await: promise를 더욱 깔끔하게 사용하기 위한 syntactic sugar
async function fetchUser() {
// do network request in 10 secs...
return "sol";
}
const user = fetchUser();
user.then(console.log);
console.log(user);
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function getApple() {
await delay(1000);
return "apple";
}
async function getBanana() {
await delay(1000);
return "banana";
}
async function pickFruits() {
try {
const applePromise = getApple();
const bananaPromise = getBanana();
const apple = await applePromise;
const banana = await bananaPromise;
return `${apple} + ${banana}`;
} catch (error) {
console.log(error);
}
}
pickFruits().then(console.log);
공유 데이터의 동시 접근(concurrent access)은 데이터 불일치(inconsistency)를 발생시킬 수 있음.
=> 일관성 유지를 위해 협력 프로세스 간의 실행 순서를 정해주는 메커니즘이 필요!
race condition: 여러 개의 프로세스들이 공유 데이터에 동시 접근하여 경쟁하는 상태
Concurrent process는 반드시 동기화(synchronize)되어야 함!
Storage Box를 공유하는 Execution Box가 여러 개인 경우, race condition이 발생할 가능성이 있음!
i) 커널 수행 중 인터럽트 발생
커널모드 수행 중 인터럽트가 발생하여 인터럽트 처리루틴이 수행됨.
양쪽 다 커널 코드이기 때문에 커널 주소공간을 공유하게 됨.
✔️ 해결방법
커널에서 하던 작업을 모드 끝낸 다음에야 인터럽트를 받아들임.
ii) 프로세스가 시스템 콜을 하여 커널모드로 수행 중일 때 문맥 교환 발생
시스템 콜을 하는 동안에는 커널의 주소공간의 데이터에 접근하게 됨.
이 작업 중간에 CPU를 가져가면 race condition이 발생함.
✔️ 해결방법
커널모드에서 사용자모드로 전환되면 CPU를 가져가게 함.
iii) 멀티프로세서에서 공유 메모리 내의 커널 모드
멀티프로세서 환경에서는 어떤 CPU가 마지막으로 동작을 수행했는지가 관건이 됨.
✔️ 해결방법
한 번에 하나의 CPU만 커널에 들어갈 수 있게 하거나, 커널 내부에 있는 각 공유 데이터에 접근할 때마다 그 데이터에 대해 lock/unlock을 함.
n개의 프로세스가 공유 데이터를 동시에 사용하기를 원하는 경우, 각 프로세스의 code segment에는 공유 데이터에 접근하는 코드인 critical-section이 존재함.
하나의 프로세스가 critical section에 있을 때, 다른 모든 프로세스는 들어갈 수 없어야 함!
✔️ 프로세스의 일반적 구조
do{
entry section
critical section
exit section
}while(1);
프로세스들은 수행의 동기화를 위해 몇몇의 변수를 공유할 수 있음. => synchronization variable
1) Mutual Exclusion; 상호 배제
프로세스가 critical section 부분을 수행 중이면, 다른 모든 프로세스들은 그들의 critical section에 들어가면 안 됨.
2) Progress; 진행
아무도 critical section에 있지 않은 상태에서 critical section에 들어가고자 하는 프로세스가 있으면 critical section에 들어가게 함.
3) Bounded Waiting; 유한 대기
프로세스가 critical section에 들어가려고 요청한 후부터 그 요청이 허용될 때까지 다른 프로세스들이 critical section에 들어가는 횟수에 한계가 설정되어야 함.
💡 critical section 해결하기 위한 대표적인 알고리즘이 바로 'Peterson's Algorithm'
하드웨어적으로 Test & modify를 atomic하게 수행할 수 있도록 지원해줌.
[유튜브] 유튜브 드림코딩 자바스크립트 기초 강의
[강의] KOCW 이화여자대학교 반효경 교수 <운영체제> 강의