μ€λ λ(thread)λ, μ»΄ν¨ν° νλ‘μΈμ€ λ΄μμ μ€νλλ κ°μ₯ μμ μ€ν λ¨μμ΄λ€. μ€λ λλ νλ‘μΈμ€ λ΄μμ λ 립μ μΌλ‘ μ€νλλ μ¬λ¬ μμ μ λνλ΄λ©°, νλ‘μΈμ€ λ΄μμ 곡μ μμμ νμ©νλ©΄μ λμμ μ€νλ μ μλ€.
μ€λ λκ° μ¬λ¬ κ° λͺ¨μ΄λ©΄ νλ‘μΈμ€κ° λλ€. νλ‘μΈμ€λ μ΄μ체μ μμμ λ 립μ μΌλ‘ μ€νλλ νλ‘κ·Έλ¨μ μ€ν μΈμ€ν΄μ€λ₯Ό λνλ΄λ©°, νλ‘μΈμ€ λ΄μμλ νλ μ΄μμ μ€λ λκ° μ€νλ μ μλ€. μ€λ λλ νλ‘μΈμ€ λ΄μμ λμνλ μμ μ€ν λ¨μμ΄λ©°, κ°μ νλ‘μΈμ€ λ΄μ μ€λ λλ λ©λͺ¨λ¦¬ λ° μμμ 곡μ νλ€.
νλ‘μΈμ€λ λ 립μ μΈ λ©λͺ¨λ¦¬ 곡κ°κ³Ό μμμ κ°μ§λ©°, λ€λ₯Έ νλ‘μΈμ€μ μμ ν 격리λμ΄ μλ€. λ°λ©΄, μ€λ λλ κ°μ νλ‘μΈμ€ λ΄μμ μ€νλλ―λ‘ νλ‘μΈμ€μ μ£Όμ 곡κ°κ³Ό μμμ 곡μ νλ€.
μ¬λ¬ μ€λ λκ° νλμ νλ‘μΈμ€ λ΄μμ λμνλ©΄, μ΄λ¬ν μ€λ λ κ°μ λ°μ΄ν° λ° μμμ 곡μ νλ©°, νλ‘μΈμ€μ μ€νμ ν¨μ¨μ μΌλ‘ κ΄λ¦¬ν μ μλ€. μ΄λ¬ν ꡬ쑰λ₯Ό μ¬μ©νλ©΄ λ©ν°μ€λ λ νλ‘κ·Έλλ°μ ν΅ν΄ λ³λ ¬ μ²λ¦¬μ λμμ±μ ꡬννκ³ , μ±λ₯μ ν₯μμν¬ μ μλ€.
μμ½νλ©΄, νλ‘μΈμ€λ νλ‘κ·Έλ¨μ μ€ν λ¨μλ₯Ό λνλ΄λ©°, νλ‘μΈμ€ λ΄μμ μ¬λ¬ μ€λ λκ° μ€νλ μ μλ€. μ€λ λλ νλ‘μΈμ€ λ΄μμ μμ μ€ν λ¨μλ‘, νλ‘μΈμ€μ μμμ 곡μ νμ¬ νλ ₯νμ¬ μμ μ μννλ€.
κ²½λμ±: μ€λ λλ νλ‘μΈμ€ λ΄μ λ€λ₯Έ μ€λ λμ κ°μ μ£Όμ 곡κ°κ³Ό μμμ 곡μ νλ―λ‘ νλ‘μΈμ€λ³΄λ€ κ²½λνλ©° μμ± λ° μ κ±°κ° λΉ λ₯΄λ€.
λμμ±: λ€μμ μ€λ λκ° λμμ μ€νλ μ μμ΄ λ©ν°μ½μ΄ CPUμμ λ³λ ¬ μ²λ¦¬λ₯Ό μ§μνκ³ μ±λ₯μ ν₯μμν¬ μ μλ€.
곡μ μμ: μ€λ λλ κ°μ νλ‘μΈμ€ λ΄μμ 곡μ λ©λͺ¨λ¦¬ 곡κ°μ κ°μ§λ―λ‘, λ°μ΄ν° λ° μμμ λν 곡μ μ λκΈ°ν κ΄λ¦¬κ° νμνλ€.
λ 립μ±: μ€λ λλ μλ‘ λ 립μ μΌλ‘ μ€νλκΈ° λλ¬Έμ, νλμ μ€λ λμμ λ°μν μ€λ₯κ° λ€λ₯Έ μ€λ λμ μν₯μ λ―ΈμΉμ§ μλλ€.
λ³λ ¬ μ²λ¦¬: λ©ν°μ½μ΄ CPUμμ μ€λ λλ₯Ό μ¬μ©νμ¬ λ³λ ¬ κ³μ°μ μννμ¬ μ±λ₯μ ν₯μμν¨λ€.
μλ΅μ± ν₯μ: λ€μ€ μ€λ λλ₯Ό μ¬μ©νμ¬ μμ© νλ‘κ·Έλ¨μ΄ μ¬μ©μ μ λ ₯μ λΉ λ₯΄κ² μλ΅νλλ‘ νλ€.
λμμ± μ μ΄: λ€λ₯Έ μ€λ λ κ°μ 곡μ λ°μ΄ν° λ° μμμ λν μ κ·Όμ μ‘°μ νκ³ λκΈ°νλ₯Ό κ΄λ¦¬νμ¬ λ°μ΄ν° μΌκ΄μ±μ μ μ§νλ€.
λ°±κ·ΈλΌμ΄λ μμ : μ€λ λλ₯Ό μ¬μ©νμ¬ λ°±κ·ΈλΌμ΄λμμ μμ μ μννκ³ , μ£Ό μ€λ λκ° λΈλ‘νΉλμ§ μλλ‘ νλ€.
νμ΄μ¬κ³Ό μλ°μ μ€λ λμμμ μ£Όμ μ°¨μ΄μ μ λ€μκ³Ό κ°λ€.
μ€λ λ λͺ¨λΈ
νμ΄μ¬: CPython, νμ΄μ¬μ νμ€ κ΅¬ν체, GIL (Global Interpreter Lock)μ΄λΌκ³ λΆλ¦¬λ μ κΈμ μ¬μ©νμ¬ λ©ν°μ€λ λ νλ‘κ·Έλλ°μ μ ννλ€. GILμ νμ΄μ¬ μΈν°ν리ν°κ° ν λ²μ νλμ μ€λ λλ§ μ½λλ₯Ό μ€ννλλ‘ κ°μ νλ λ©μ»€λμ¦μΌλ‘, CPU λ°μ΄λ μμ μμ λ©ν°μ½μ΄ CPUλ₯Ό ν¨μ¨μ μΌλ‘ νμ©νμ§ λͺ»νκ² νλ€. λ°λΌμ νμ΄μ¬μ I/O λ°μ΄λ μμ μμλ μ€λ λλ₯Ό μ¬μ©ν μ μμ§λ§, CPU λ°μ΄λ μμ μμλ λ³λ ¬μ±μ ν₯μμν€κΈ° μ΄λ ΅λ€.
μλ°: μλ°λ λ©ν°μ€λ λ νκ²½μ μ§μνλ©° GILκ³Ό κ°μ μ μ½ μ¬νμ΄ μλ€. μλ° μ€λ λλ μ΄μ체μ λ° JVMμ μ€μΌμ€λ§μ λ°λΌ λ³λ ¬λ‘ μ€νλλ€. μ΄λ‘ μΈν΄ CPU λ°μ΄λ μμ μμ λ©ν°μ½μ΄ CPUλ₯Ό ν¨κ³Όμ μΌλ‘ νμ©ν μ μλ€.
μ€λ λ μμ± λ°©μ
νμ΄μ¬: νμ΄μ¬μ threading
λͺ¨λμ μ¬μ©νμ¬ μ€λ λλ₯Ό μμ±νκ³ κ΄λ¦¬ν©λλ€. μ€λ λλ₯Ό ν΄λμ€λ‘ μ μνκ±°λ ν¨μλ‘ μ μν ν, Thread
ν΄λμ€λ₯Ό μ΄μ©νμ¬ μ€λ λ κ°μ²΄λ₯Ό μμ±νλ€.
μλ°: μλ°λ μ€λ λλ₯Ό λ§λ€κΈ° μν΄ Thread
ν΄λμ€λ₯Ό μμνκ±°λ Runnable
μΈν°νμ΄μ€λ₯Ό ꡬννλ λ°©μμ μ¬μ©νλ€. λν, μλ°λ μ€λ λλ₯Ό μ€λ λ νμ ν΅ν΄ ν¨μ¨μ μΌλ‘ κ΄λ¦¬ν μ μλ λ€μν λΌμ΄λΈλ¬λ¦¬μ ν΄λμ€λ₯Ό μ 곡νλ€.
λκΈ°ν:
νμ΄μ¬: νμ΄μ¬μ GILλ‘ μΈν΄ λμμ νλμ μ€λ λλ§ μ½λλ₯Ό μ€ννλ―λ‘, 곡μ μμμ λν λκΈ°νκ° μ μ νκ² μ΄λ£¨μ΄μ ΈμΌ νλ€.
μλ°: μλ°λ λͺ
μμ μΈ λκΈ°ν λ©μ»€λμ¦μ μ§μνλ©°, synchronized
ν€μλμ λ½μ μ¬μ©νμ¬ μ€λ λ κ°μ λκΈ°νλ₯Ό μ μ΄νλ€. λν, μλ°λ Concurrent
ν¨ν€μ§μ java.util.concurrent
λΌμ΄λΈλ¬λ¦¬λ₯Ό ν΅ν΄ κ³ κΈ λμμ± λ° μ€λ λ κ΄λ¦¬ κΈ°λ₯μ μ 곡νλ€.
μλ¬ μ²λ¦¬:
νμ΄μ¬: νμ΄μ¬ μ€λ λμμ λ°μνλ μμΈλ ν΄λΉ μ€λ λμμ μ²λ¦¬λμ§ μμΌλ©΄ λ©μΈ μ€λ λλ‘ μ νλλ―λ‘ μ£Όμκ° νμνλ€.
μλ°: μλ° μ€λ λλ μμΈλ₯Ό μ²λ¦¬νκ±°λ μ νν λ λͺ μμ μΈ μμΈ μ²λ¦¬ λ©μ»€λμ¦μ μ¬μ©νλ€.
μ€λ λ κ΄λ¦¬:
νμ΄μ¬: νμ΄μ¬ μ€λ λλ μΌλ°μ μΌλ‘ μΈλΆ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ μ€λ λ ν λ° κ³ κΈ μ€λ λ κ΄λ¦¬λ₯Ό ꡬνν΄μΌ νλ€.
μλ°: μλ°λ java.util.concurrent
λΌμ΄λΈλ¬λ¦¬μ Executor
νλ μμν¬λ₯Ό ν΅ν΄ μ€λ λ ν λ° μ€λ λ κ΄λ¦¬λ₯Ό κ°νΈνκ² μνν μ μλ λ€μν λꡬλ₯Ό μ 곡νλ€.
import threading
import time
# 첫 λ²μ§Έ μ€λ λμμ μ€νν ν¨μ
def thread_function_1():
for i in range(5):
print("μ€λ λ 1: μ€ν μ€")
time.sleep(1)
# λ λ²μ§Έ μ€λ λμμ μ€νν ν¨μ
def thread_function_2():
for i in range(5):
print("μ€λ λ 2: μ€ν μ€")
time.sleep(1)
# μ€λ λ κ°μ²΄ μμ±
thread1 = threading.Thread(target=thread_function_1)
thread2 = threading.Thread(target=thread_function_2)
# μ€λ λ μμ
thread1.start()
thread2.start()
# λͺ¨λ μ€λ λκ° μ€νμ λ§μΉκΈ°λ₯Ό κΈ°λ€λ¦Ό
thread1.join()
thread2.join()
print("λͺ¨λ μ€λ λκ° μ’
λ£λμμ΅λλ€.")
μ΄ μ½λμμ λ κ°μ μ€λ λλ₯Ό μμ±νκ³ κ° μ€λ λλ μλ‘ λ€λ₯Έ ν¨μλ₯Ό μ€ννλ€. κ° μ€λ λλ 1μ΄ κ°κ²©μΌλ‘ λ©μμ§λ₯Ό μΆλ ₯νκ³ 5λ² λ°λ³΅ν ν μ’ λ£λλ€. threading.Threadλ₯Ό μ¬μ©νμ¬ μ€λ λ κ°μ²΄λ₯Ό μμ±νκ³ start() λ©μλλ‘ μ€λ λλ₯Ό μμνλ€. λ§μ§λ§μΌλ‘ join() λ©μλλ₯Ό μ¬μ©νμ¬ λͺ¨λ μ€λ λκ° μ’ λ£λ λκΉμ§ λκΈ°νλ€.
μ μ½λλ₯Ό μ€ννλ©΄ λ κ°μ μ€λ λκ° λ³λ ¬λ‘ μ€νλλ©° "μ€λ λ 1"κ³Ό "μ€λ λ 2"μ λ©μμ§λ₯Ό λ²κ°μκ°λ©° μΆλ ₯ν κ²μ΄λ€.
class CountdownThread extends Thread {
@Override
public void run() {
for (int i = 5; i > 0; i--) {
System.out.println(getName() + ": " + i);
try {
Thread.sleep(1000); // 1μ΄ λκΈ°
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadExample {
public static void main(String[] args) {
CountdownThread thread1 = new CountdownThread();
CountdownThread thread2 = new CountdownThread();
// μ€λ λ μμ
thread1.start();
thread2.start();
try {
// λ©μΈ μ€λ λκ° thread1κ³Ό thread2μ μμ
μ κΈ°λ€λ¦Ό
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("λͺ¨λ μ€λ λκ° μ’
λ£λμμ΅λλ€.");
}
}
μ΄ μ½λλ κ°λ¨ν μΉ΄μ΄νΈ λ€μ΄ μμ
μ΄λ€.
μ΄ μ½λμμ CountdownThread
λ Thread
ν΄λμ€λ₯Ό μμνκ³ run
λ©μλλ₯Ό μ€λ²λΌμ΄λνμ¬ μ€λ λκ° μ€νν μμ
μ μ μνλ€.
ThreadExample
ν΄λμ€μμλ CountdownThread
μ μΈμ€ν΄μ€ λ κ°λ₯Ό μμ±νκ³ κ°κ°μ μ€λ λλ₯Ό μμνλ€. κ·Έλ° λ€μ join
λ©μλλ₯Ό μ¬μ©νμ¬ λ©μΈ μ€λ λκ° thread1
κ³Ό thread2
μ μμ
μ΄ λλ λκΉμ§ λκΈ°νλλ‘ νλ€. λ°λΌμ λͺ¨λ μ€λ λκ° μ’
λ£λ ν "λͺ¨λ μ€λ λκ° μ’
λ£λμμ΅λλ€."λΌλ λ©μμ§κ° μΆλ ₯λλ€.