thread(python vs java)

혜쿰·2023λ…„ 10μ›” 17일
0
post-thumbnail

πŸ›’ κ°œλ…

πŸ” μŠ€λ ˆλ“œλž€?

μŠ€λ ˆλ“œ(thread)λž€, 컴퓨터 ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ μ‹€ν–‰λ˜λŠ” κ°€μž₯ μž‘μ€ μ‹€ν–‰ λ‹¨μœ„μ΄λ‹€. μŠ€λ ˆλ“œλŠ” ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ λ…λ¦½μ μœΌλ‘œ μ‹€ν–‰λ˜λŠ” μ—¬λŸ¬ μž‘μ—…μ„ λ‚˜νƒ€λ‚΄λ©°, ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ 곡유 μžμ›μ„ ν™œμš©ν•˜λ©΄μ„œ λ™μ‹œμ— 싀행될 수 μžˆλ‹€.

πŸ” ν”„λ‘œμ„ΈμŠ€λž€?

μŠ€λ ˆλ“œκ°€ μ—¬λŸ¬ 개 λͺ¨μ΄λ©΄ ν”„λ‘œμ„ΈμŠ€κ°€ λœλ‹€. ν”„λ‘œμ„ΈμŠ€λŠ” 운영체제 μƒμ—μ„œ λ…λ¦½μ μœΌλ‘œ μ‹€ν–‰λ˜λŠ” ν”„λ‘œκ·Έλž¨μ˜ μ‹€ν–‰ μΈμŠ€ν„΄μŠ€λ₯Ό λ‚˜νƒ€λ‚΄λ©°, ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œλŠ” ν•˜λ‚˜ μ΄μƒμ˜ μŠ€λ ˆλ“œκ°€ 싀행될 수 μžˆλ‹€. μŠ€λ ˆλ“œλŠ” ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ λ™μž‘ν•˜λŠ” μž‘μ€ μ‹€ν–‰ λ‹¨μœ„μ΄λ©°, 같은 ν”„λ‘œμ„ΈμŠ€ λ‚΄μ˜ μŠ€λ ˆλ“œλŠ” λ©”λͺ¨λ¦¬ 및 μžμ›μ„ κ³΅μœ ν•œλ‹€.

πŸ” μŠ€λ ˆλ“œμ™€ ν”„λ‘œμ„ΈμŠ€ κ΅¬λΆ„ν•˜κΈ°

ν”„λ‘œμ„ΈμŠ€λŠ” 독립적인 λ©”λͺ¨λ¦¬ 곡간과 μžμ›μ„ 가지며, λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€μ™€ μ™„μ „νžˆ κ²©λ¦¬λ˜μ–΄ μžˆλ‹€. 반면, μŠ€λ ˆλ“œλŠ” 같은 ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ μ‹€ν–‰λ˜λ―€λ‘œ ν”„λ‘œμ„ΈμŠ€μ˜ μ£Όμ†Œ 곡간과 μžμ›μ„ κ³΅μœ ν•œλ‹€.

μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ ν•˜λ‚˜μ˜ ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ λ™μž‘ν•˜λ©΄, μ΄λŸ¬ν•œ μŠ€λ ˆλ“œ 간에 데이터 및 μžμ›μ„ κ³΅μœ ν•˜λ©°, ν”„λ‘œμ„ΈμŠ€μ˜ 싀행을 효율적으둜 관리할 수 μžˆλ‹€. μ΄λŸ¬ν•œ ꡬ쑰λ₯Ό μ‚¬μš©ν•˜λ©΄ λ©€ν‹°μŠ€λ ˆλ“œ ν”„λ‘œκ·Έλž˜λ°μ„ 톡해 병렬 μ²˜λ¦¬μ™€ λ™μ‹œμ„±μ„ κ΅¬ν˜„ν•˜κ³ , μ„±λŠ₯을 ν–₯μƒμ‹œν‚¬ 수 μžˆλ‹€.

μš”μ•½ν•˜λ©΄, ν”„λ‘œμ„ΈμŠ€λŠ” ν”„λ‘œκ·Έλž¨μ˜ μ‹€ν–‰ λ‹¨μœ„λ₯Ό λ‚˜νƒ€λ‚΄λ©°, ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ 싀행될 수 μžˆλ‹€. μŠ€λ ˆλ“œλŠ” ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ μž‘μ€ μ‹€ν–‰ λ‹¨μœ„λ‘œ, ν”„λ‘œμ„ΈμŠ€μ˜ μžμ›μ„ κ³΅μœ ν•˜μ—¬ ν˜‘λ ₯ν•˜μ—¬ μž‘μ—…μ„ μˆ˜ν–‰ν•œλ‹€.

πŸ›’ νŠΉμ§•

  • κ²½λŸ‰μ„±: μŠ€λ ˆλ“œλŠ” ν”„λ‘œμ„ΈμŠ€ λ‚΄μ˜ λ‹€λ₯Έ μŠ€λ ˆλ“œμ™€ 같은 μ£Όμ†Œ 곡간과 μžμ›μ„ κ³΅μœ ν•˜λ―€λ‘œ ν”„λ‘œμ„ΈμŠ€λ³΄λ‹€ κ²½λŸ‰ν•˜λ©° 생성 및 μ œκ±°κ°€ λΉ λ₯΄λ‹€.

  • λ™μ‹œμ„±: λ‹€μˆ˜μ˜ μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— 싀행될 수 μžˆμ–΄ λ©€ν‹°μ½”μ–΄ CPUμ—μ„œ 병렬 처리λ₯Ό μ§€μ›ν•˜κ³  μ„±λŠ₯을 ν–₯μƒμ‹œν‚¬ 수 μžˆλ‹€.

  • 곡유 μžμ›: μŠ€λ ˆλ“œλŠ” 같은 ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ 곡유 λ©”λͺ¨λ¦¬ 곡간을 κ°€μ§€λ―€λ‘œ, 데이터 및 μžμ›μ— λŒ€ν•œ κ³΅μœ μ™€ 동기화 관리가 ν•„μš”ν•˜λ‹€.

  • 독립성: μŠ€λ ˆλ“œλŠ” μ„œλ‘œ λ…λ¦½μ μœΌλ‘œ μ‹€ν–‰λ˜κΈ° λ•Œλ¬Έμ—, ν•˜λ‚˜μ˜ μŠ€λ ˆλ“œμ—μ„œ λ°œμƒν•œ 였λ₯˜κ°€ λ‹€λ₯Έ μŠ€λ ˆλ“œμ— 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠλŠ”λ‹€.

πŸ›’ μš©λ„

  • 병렬 처리: λ©€ν‹°μ½”μ–΄ CPUμ—μ„œ μŠ€λ ˆλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 병렬 계산을 μˆ˜ν–‰ν•˜μ—¬ μ„±λŠ₯을 ν–₯μƒμ‹œν‚¨λ‹€.

  • 응닡성 ν–₯상: 닀쀑 μŠ€λ ˆλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ‘μš© ν”„λ‘œκ·Έλž¨μ΄ μ‚¬μš©μž μž…λ ₯에 λΉ λ₯΄κ²Œ μ‘λ‹΅ν•˜λ„λ‘ ν•œλ‹€.

  • λ™μ‹œμ„± μ œμ–΄: λ‹€λ₯Έ μŠ€λ ˆλ“œ 간에 곡유 데이터 및 μžμ›μ— λŒ€ν•œ 접근을 μ‘°μ ˆν•˜κ³  동기화λ₯Ό κ΄€λ¦¬ν•˜μ—¬ 데이터 일관성을 μœ μ§€ν•œλ‹€.

  • λ°±κ·ΈλΌμš΄λ“œ μž‘μ—…: μŠ€λ ˆλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ λ°±κ·ΈλΌμš΄λ“œμ—μ„œ μž‘μ—…μ„ μˆ˜ν–‰ν•˜κ³ , μ£Ό μŠ€λ ˆλ“œκ°€ λΈ”λ‘œν‚Ήλ˜μ§€ μ•Šλ„λ‘ ν•œλ‹€.

πŸ›’ python vs java

파이썬과 μžλ°”μ˜ μŠ€λ ˆλ“œμ—μ„œμ˜ μ£Όμš” 차이점은 λ‹€μŒκ³Ό κ°™λ‹€.

  1. μŠ€λ ˆλ“œ λͺ¨λΈ

    • 파이썬: CPython, 파이썬의 ν‘œμ€€ κ΅¬ν˜„μ²΄, GIL (Global Interpreter Lock)이라고 λΆˆλ¦¬λŠ” μž κΈˆμ„ μ‚¬μš©ν•˜μ—¬ λ©€ν‹°μŠ€λ ˆλ“œ ν”„λ‘œκ·Έλž˜λ°μ„ μ œν•œν•œλ‹€. GIL은 파이썬 인터프리터가 ν•œ λ²ˆμ— ν•˜λ‚˜μ˜ μŠ€λ ˆλ“œλ§Œ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ„λ‘ κ°•μ œν•˜λŠ” λ©”μ»€λ‹ˆμ¦˜μœΌλ‘œ, CPU λ°”μš΄λ“œ μž‘μ—…μ—μ„œ λ©€ν‹°μ½”μ–΄ CPUλ₯Ό 효율적으둜 ν™œμš©ν•˜μ§€ λͺ»ν•˜κ²Œ ν•œλ‹€. λ”°λΌμ„œ νŒŒμ΄μ¬μ€ I/O λ°”μš΄λ“œ μž‘μ—…μ—μ„œλŠ” μŠ€λ ˆλ“œλ₯Ό μ‚¬μš©ν•  수 μžˆμ§€λ§Œ, CPU λ°”μš΄λ“œ μž‘μ—…μ—μ„œλŠ” 병렬성을 ν–₯μƒμ‹œν‚€κΈ° μ–΄λ ΅λ‹€.

    • μžλ°”: μžλ°”λŠ” λ©€ν‹°μŠ€λ ˆλ“œ ν™˜κ²½μ„ μ§€μ›ν•˜λ©° GILκ³Ό 같은 μ œμ•½ 사항이 μ—†λ‹€. μžλ°” μŠ€λ ˆλ“œλŠ” 운영체제 및 JVM의 μŠ€μΌ€μ€„λ§μ— 따라 λ³‘λ ¬λ‘œ μ‹€ν–‰λœλ‹€. 이둜 인해 CPU λ°”μš΄λ“œ μž‘μ—…μ—μ„œ λ©€ν‹°μ½”μ–΄ CPUλ₯Ό 효과적으둜 ν™œμš©ν•  수 μžˆλ‹€.

  2. μŠ€λ ˆλ“œ 생성 방식

    • 파이썬: νŒŒμ΄μ¬μ€ threading λͺ¨λ“ˆμ„ μ‚¬μš©ν•˜μ—¬ μŠ€λ ˆλ“œλ₯Ό μƒμ„±ν•˜κ³  κ΄€λ¦¬ν•©λ‹ˆλ‹€. μŠ€λ ˆλ“œλ₯Ό 클래슀둜 μ •μ˜ν•˜κ±°λ‚˜ ν•¨μˆ˜λ‘œ μ •μ˜ν•œ ν›„, Thread 클래슀λ₯Ό μ΄μš©ν•˜μ—¬ μŠ€λ ˆλ“œ 객체λ₯Ό μƒμ„±ν•œλ‹€.

    • μžλ°”: μžλ°”λŠ” μŠ€λ ˆλ“œλ₯Ό λ§Œλ“€κΈ° μœ„ν•΄ Thread 클래슀λ₯Ό μƒμ†ν•˜κ±°λ‚˜ Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” 방식을 μ‚¬μš©ν•œλ‹€. λ˜ν•œ, μžλ°”λŠ” μŠ€λ ˆλ“œλ₯Ό μŠ€λ ˆλ“œ 풀을 톡해 효율적으둜 관리할 수 μžˆλŠ” λ‹€μ–‘ν•œ λΌμ΄λΈŒλŸ¬λ¦¬μ™€ 클래슀λ₯Ό μ œκ³΅ν•œλ‹€.

  3. 동기화:

    • 파이썬: νŒŒμ΄μ¬μ€ GIL둜 인해 λ™μ‹œμ— ν•˜λ‚˜μ˜ μŠ€λ ˆλ“œλ§Œ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ―€λ‘œ, 곡유 μžμ›μ— λŒ€ν•œ 동기화가 μ μ ˆν•˜κ²Œ 이루어져야 ν•œλ‹€.

    • μžλ°”: μžλ°”λŠ” λͺ…μ‹œμ μΈ 동기화 λ©”μ»€λ‹ˆμ¦˜μ„ μ§€μ›ν•˜λ©°, synchronized ν‚€μ›Œλ“œμ™€ 락을 μ‚¬μš©ν•˜μ—¬ μŠ€λ ˆλ“œ κ°„μ˜ 동기화λ₯Ό μ œμ–΄ν•œλ‹€. λ˜ν•œ, μžλ°”λŠ” Concurrent νŒ¨ν‚€μ§€μ™€ java.util.concurrent 라이브러리λ₯Ό 톡해 κ³ κΈ‰ λ™μ‹œμ„± 및 μŠ€λ ˆλ“œ 관리 κΈ°λŠ₯을 μ œκ³΅ν•œλ‹€.

  4. μ—λŸ¬ 처리:

    • 파이썬: 파이썬 μŠ€λ ˆλ“œμ—μ„œ λ°œμƒν•˜λŠ” μ˜ˆμ™ΈλŠ” ν•΄λ‹Ή μŠ€λ ˆλ“œμ—μ„œ μ²˜λ¦¬λ˜μ§€ μ•ŠμœΌλ©΄ 메인 μŠ€λ ˆλ“œλ‘œ μ „νŒŒλ˜λ―€λ‘œ μ£Όμ˜κ°€ ν•„μš”ν•˜λ‹€.

    • μžλ°”: μžλ°” μŠ€λ ˆλ“œλŠ” μ˜ˆμ™Έλ₯Ό μ²˜λ¦¬ν•˜κ±°λ‚˜ μ „νŒŒν•  λ•Œ λͺ…μ‹œμ μΈ μ˜ˆμ™Έ 처리 λ©”μ»€λ‹ˆμ¦˜μ„ μ‚¬μš©ν•œλ‹€.

  5. μŠ€λ ˆλ“œ 관리:

    • 파이썬: 파이썬 μŠ€λ ˆλ“œλŠ” 일반적으둜 μ™ΈλΆ€ 라이브러리λ₯Ό μ‚¬μš©ν•˜μ—¬ μŠ€λ ˆλ“œ ν’€ 및 κ³ κΈ‰ μŠ€λ ˆλ“œ 관리λ₯Ό κ΅¬ν˜„ν•΄μ•Ό ν•œλ‹€.

    • μžλ°”: μžλ°”λŠ” java.util.concurrent λΌμ΄λΈŒλŸ¬λ¦¬μ™€ Executor ν”„λ ˆμž„μ›Œν¬λ₯Ό 톡해 μŠ€λ ˆλ“œ ν’€ 및 μŠ€λ ˆλ“œ 관리λ₯Ό κ°„νŽΈν•˜κ²Œ μˆ˜ν–‰ν•  수 μžˆλŠ” λ‹€μ–‘ν•œ 도ꡬλ₯Ό μ œκ³΅ν•œλ‹€.

πŸ›’ μ½”λ“œ μ˜ˆμ‹œ

πŸ” python

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"의 λ©”μ‹œμ§€λ₯Ό λ²ˆκ°ˆμ•„κ°€λ©° 좜λ ₯ν•  것이닀.

πŸ” java

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의 μž‘μ—…μ΄ 끝날 λ•ŒκΉŒμ§€ λŒ€κΈ°ν•˜λ„λ‘ ν•œλ‹€. λ”°λΌμ„œ λͺ¨λ“  μŠ€λ ˆλ“œκ°€ μ’…λ£Œλœ ν›„ "λͺ¨λ“  μŠ€λ ˆλ“œκ°€ μ’…λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€."λΌλŠ” λ©”μ‹œμ§€κ°€ 좜λ ₯λœλ‹€.

0개의 λŒ“κΈ€