Загружаем каталог…
Загружаем каталог…
이번 글에서는 프로그램을 실행할 때 프로세스와 스레드가 무엇을 나누고 공유하는지 정리해보려고 합니다. 정의만 따로 외우기보다, 공유 값을 바꾸는 작은 예시와 함께 살펴보겠습니다. 두 요청이 같은 값을 각각 1씩 올린다고 가정해보겠습니다. 2가 늘어야 할 것 같은데 결과가 1만 늘었다면 어디를 확인해야 할까요? 먼저 실행 흐름이 무엇을 공유하는지 부터 보겠습니다. 오늘 알아볼 것 변수와 함수, CPU가 계산하고 메모리에 값을 저장한다는 정도를 알고 있으면 시작할 수 있습니다. 운영체제 코드를 미리 읽을 필요는 없습니다. 읽고 나면 다음 세 가지를 설명하는 것이 목표입니다. 프로그램과 프로세스를 구분한다. 같은 프로세스의 스레드가 공유하는 것과 따로 갖는 것을 구분한다. 공유 값의 갱신 순서를 따라가며 결과가 달라지는 이유를 설명한다. 프로그램은 파일이고, 프로세스는 실행 중인 상태다 디스크에 놓인 프로그램만으로는 계산이 진행되지 않습니다. 실행하면 운영체제가 실행 상태와 자원을 관리합니다. 이 실행 중인 프로그램을 프로세스라고 생각하면 출발하기 쉽습니다. 프로세스에는 코드와 데이터가 들어가는 주소 공간, 현재 실행 위치, CPU 상태 등 실행에 필요한 정보가 있습니다. 프로그램 하나를 여러 번 실행하면 여러 프로세스가 만들어질 수 있습니다. OSTEP의 프로세스 장 에서 이 기본 구조를 설명합니다. 스레드는 같은 프로세스 안의 실행 흐름이다 하나의 프로세스 안에 실행 흐름을 여러 개 둘 수 있습니다. 스레드는 이런 실행 흐름입니다. POSIX 스레드는 같은 프로세스의 데이터와 힙을 공유하고, 각자 스택을 갖습니다. 각 스레드의 실행 위치와 CPU 상태도 구분해야 실행을 이어 갈 수 있습니다. pthreads(7) , OSTEP의 스레드 장 다음 그림은 별도 주소 공간과 프로세스 내부 공유 영역을 비교합니다. 이미지가 보이지 않아도 아래 설명으로 같은 내용을 확인할 수 있습니다. 그림의 핵심은 스레드 1과 2가 같은 데이터에 접근한다는 점입니다. 주소 공간이 구분된다고 프로세스 사이에 아무것도 공유할 수 없다는 뜻은 아닙니다. 공유 메모리나 파일 같은 자원으로 통신할 수 있습니다. Linux의 fork() 도 별도 메모리 공간을 만들지만 상속된 파일 기술자가 같은 열린 파일 설명을 참조할 수 있습니다. fork(2) 비교 서로 다른 프로세스 같은 프로세스의 스레드 일반적인 주소 공간 각각 구분 공유 실행 위치와 CPU 상태 각각 관리 각각 관리 스택 각 실행 흐름이 사용 스레드별로 사용 같은 값 변경 명시적인 공유·통신 방식 필요 공유 값에 직접 접근 가능 여기서 “스택이 따로 있다”는 말은 보안 격리를 뜻하지 않습니다. 같은 주소 공간 안에서는 다른 스레드가 유효한 포인터를 통해 스택의 데이터에 접근할 수도 있습니다. 숫자 두 번 올렸는데 한 번만 반영되는 이유 공유 값 count 가 100이라고 가정해보겠습니다. 두 스레드가 각각 한 번씩 값을 올립니다. 아래는 실제 측정 로그가 아니라, 가능한 실행 순서를 손으로 펼친 예시입니다. 값을 올리는 작업을 읽기 → 1 더하기 → 쓰기 로 나눠보겠습니다. 이 전체가 원자적으로 보호된다고 가정하지 않습니다. 순서 스레드 A 스레드 B 공유 count 1 100 읽기 대기 100 2 대기 100 읽기 100 3 101 계산 후 쓰기 대기 101 4 대기 읽었던 100으로 101 계산 후 쓰기 101 둘 다 일을 마쳤지만 B는 A가 바꾼 101을 읽지 않았습니다. 이전에 읽은 100을 바탕으로 값을 덮어썼습니다. 이를 갱신 손실 예시로 볼 수 있습니다. 공유 상태를 여러 실행 흐름이 다루면 실행 순서가 결과에 영향을 줄 수 있습니다. OSTEP의 동시성과 스레드 설명 다음 JavaScript는 위 순서를 순차적으로 모의 실행 합니다. 실제 스레드를 만들거나 JavaScript 런타임의 경쟁 상태를 측정하는 코드는 아닙니다. let count = 100; const readA = count; const readB = count; count = readA + 1; count = readB + 1; console.log(`interleaved=${count}`); // interleaved=101 count = 100; count += 1; count += 1; console.log(`serialized=${count}`); // serialized=102 Node.js v24.13.1에서 실제 실행해 interleaved=101 , serialized=102 를 확인했습니다. 원래 읽었던 값으로 쓰는 경우와, 앞 작업의 결과를 읽고 다음 작업을 하는 경우를 비교하는 예시입니다. 이 순서를 그림으로 보면 오래된 읽기 결과가 어디서 쓰이는지 쉽게 보입니다. 언어별 실제 count++ 나 count += 1 의 동작을 이 그림만 보고 단정하면 안 됩니다. 런타임, 메모리 모델, 원자 연산 여부를 확인해야 합니다. 이 예시는 보호되지 않은 읽기·계산·쓰기의 문제를 설명합니다. 그럼 어떻게 보호할까? 공유 값을 다루는 전체 구간 을 함께 보호해야 합니다. 락으로 읽기·계산·쓰기를 묶으면 A가 끝난 뒤 B가 101을 읽어 102를 쓸 수 있습니다. 조건에 맞는 원자 연산이나 메시지 전달 방식도 선택지가 됩니다. 쓰는 순간에만 락을 잡고 이전 읽기를 보호하지 않으면 같은 문제가 남을 수 있습니다. “락을 사용했다”보다 “무슨 불변 조건을 어떤 구간에서 보호했나”를 확인하는 것이 중요합니다. 자세한 구현은 다음 동기화 글에서 다룰 예정입니다. 자주 헷갈리는 부분 스레드를 늘리면 항상 빨라진다? 작업의 성격, 코어 수, 대기 시간, 동기화 비용에 따라 달라집니다. 스레드 수 자체는 성능 증거가 아닙니다. 동시성이면 반드시 같은 순간 실행된다? 여러 작업을 번갈아 진행하는 것도 동시성입니다. 실제로 같은 순간 진행하는 병렬성과 구분해야 합니다. 프로세스만 나누면 공유 데이터 문제도 끝난다? 파일·DB·공유 메모리에서 같은 상태를 바꾼다면 그 상태의 동시 접근을 다시 검토해야 합니다. 세 가지 질문으로 확인해보겠습니다 1. 같은 프로그램을 두 번 실행했다. 일반 변수 하나를 바꾸면 다른 실행에도 바로 반영될까? 2. 예시를 바꿔 A가 101을 쓴 다음에 B가 값을 읽고 1을 더해 쓰면 마지막 값은? 3. 쓰기 부분만 락으로 묶으면 갱신 손실을 막을 수 있을까? 답과 해설 1. 일반적으로 별도 프로세스의 주소 공간이므로 자동 반영되지 않습니다. 별도의 공유 메모리나 통신을 구성했는지 확인해야 합니다. 2. 102입니다. 이번에는 B가 A의 결과인 101을 읽었기 때문입니다. 둘 다 100을 먼저 읽었던 원래 예시의 101과 비교해 보겠습니다. 3. 이 예시에서는 부족합니다. 읽기·계산·쓰기 전체를 같은 보호 규칙으로 묶거나 목적에 맞는 원자 연산을 사용해야 합니다. 복습과 다음 글 자료를 덮고 “프로세스는 무엇을 나누고, 스레드는 무엇을 공유하나?”를 설명해보겠습니다. 두 스레드가 번갈아 실행되는 표를 직접 다시 그린 뒤 최종 값을 계산하면 더 오래 기억하기 쉽습니다. 다음 날·3일 뒤·일주일 뒤 같은 질문을 다시 풀어보는 것을 권합니다. 틀렸다면 정의를 외우기보다 공유 영역 그림과 읽기·쓰기 순서로 돌아가 확인합니다. 다음 주제는 동시성과 병렬성, CPU 한 개가 여러 작업을 처리하는 방법 입니다. 그다음 락으로 어떤 구간을 보호해야 하는지 이어서 살펴볼 예정입니다. 후속 글은 아직 작성·게시하지 않았습니다. 자료 확인 기준 개념 설명은 OSTEP v1.10의 프로세스·동시성 장과 Linux 매뉴얼의 pthreads(7) , fork(2) 를 확인했습니다. 자료 확인과 JavaScript 예제 재실행 날짜는 2026-10-04입니다. JavaScript 코드는 실행 순서를 설명하는 모의 예제이며, 실제 멀티스레드 성능이나 원자성을 측정하지 않습니다.
То, что RADAR обнаружил и классифицировал для этой возможности. Это опубликованный источником текст, а не подтверждение, что предложение ещё действует.
같은 프로그램인데 왜 값이 꼬일까? 프로세스와 스레드 정리. 이번 글에서는 프로그램을 실행할 때 프로세스와 스레드가 무엇을 나누고 공유하는지 정리해보려고 합니다. 정의만 따로 외우기보다, 공유 값을 바꾸는 작은 예시와 함께 살펴보겠습니다. 두 요청이 같은 값을 각각 1씩 올린다고 가정해보겠습니다. 2가 늘어야 할 것 같은데 결과가 1만 늘었다면 어디를 확인해야 할까요? 먼저 실행 흐름이 무엇을 공유하는지 부터 보겠습니다. 오늘 알아볼 것 변수와 함수, CPU가 계산하고 메모리에 값을 저장한다는 정도를 알고 있으면 시작할 수 있습니다. 운영체제 코드를 미리 읽을 필요는 없습니다. 읽고 나면 다음 세 가지를 설명하는 것이 목표입니다. 프로그램과 프로세스를 구분한다. 같은 프로세스의 스레드가 공유하는 것과 따로…
Открыть источник