λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

Java/Java의 정석

Chapter 13 - μ“°λ ˆλ“œ(Thread)

Chapter 13 - μ“°λ ˆλ“œ(Thread)

1. ν”„λ‘œμ„ΈμŠ€μ™€ μ“°λ ˆλ“œ

  • process : μ‹€ν–‰ 쀑인 ν”„λ‘œκ·Έλž¨
    • OSλ‘œλΆ€ν„° 싀행에 ν•„μš”ν•œ μžμ›(λ©”λͺ¨λ¦¬)을 할당받은 ν›„ ν”„λ‘œμ„ΈμŠ€κ°€ 됨
    • 데이터, λ©”λͺ¨λ¦¬ λ“±μ˜ μžμ›, μ“°λ ˆλ“œλ‘œ ꡬ성
    • μ“°λ ˆλ“œκ°€ ν”„λ‘œμ„ΈμŠ€μ˜ μžμ›μ„ μ΄μš©ν•΄μ„œ μ‹€μ œ μž‘μ—… μˆ˜ν–‰
    • λͺ¨λ“  ν”„λ‘œμ„ΈμŠ€μ—μ„  μ΅œμ†Œ ν•˜λ‚˜μ˜ μ“°λ ˆλ“œκ°€ 쑴재
    • λ‘˜ μ΄μƒμ˜ μ“°λ ˆλ“œλ₯Ό 가지면 λ©€ν‹°μ“°λ ˆλ“œ ν”„λ‘œμ„ΈμŠ€
    • λ©”λͺ¨λ¦¬ ν•œκ³„μ— 따라 생성할 수 μžˆλŠ” μ“°λ ˆλ“œ μˆ˜κ°€ κ²°μ •

λ©€ν‹°νƒœμŠ€ν‚Ήκ³Ό λ©€ν‹°μ“°λ ˆλ”©

  • λŒ€λΆ€λΆ„μ˜ OSλŠ” λ©€ν‹°νƒœμŠ€ν‚Ή 지원
    • μ—¬λŸ¬ 개의 ν”„λ‘œμ„ΈμŠ€κ°€ λ™μ‹œμ— μ‹€ν–‰ κ°€λŠ₯
  • λ©€ν‹°μΊμŠ€νŒ…μ²˜λŸΌ λ©€ν‹° μ“°λ ˆλ”©μ€ ν•˜λ‚˜μ˜ ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ μ—¬λŸ¬ μ“°λ ˆλ“œκ°€ λ™μ‹œμ— μž‘μ—…μ„ μˆ˜ν–‰
    • μ½”μ–΄κ°€ μ•„μ£Ό 짧은 μ‹œκ°„ λ™μ•ˆ μ—¬λŸ¬ μž‘μ—…μ„ λ²ˆκ°ˆμ•„κ°€λ©° μˆ˜ν–‰ν•¨ -> λͺ¨λ‘ λ™μ‹œμ— μˆ˜ν–‰λ˜λŠ” κ²ƒμ²˜λŸΌ 느껴짐
    • 예) 파일 λ‹€μš΄λ‘œλ“œλ₯Ό ν•˜λ©΄μ„œ λ©”μ‹ μ €λ₯Ό ν•˜λŠ” 행동
  • λ§Žμ€ μ“°λ ˆλ“œλ₯Ό 가진닀고 ν”„λ‘œμ„ΈμŠ€μ˜ μ„±λŠ₯이 μ˜¬λΌκ°€λŠ” 것은 μ•„λ‹˜

λ©€ν‹°μ“°λ ˆλ”©μ˜ μž₯단점

  • μž₯점
    • CPU μ‚¬μš©λ₯  ν–₯상
    • μžμ›μ„ 더 효율적으둜 μ‚¬μš©
    • μ‚¬μš©μžμ— λŒ€ν•œ 응닡성 ν–₯상
    • μž‘μ—…μ΄ λΆ„λ¦¬λ˜μ–΄ μ½”λ“œκ°€ 간결해짐
    • ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜λŠ” 것에 λΉ„ν•΄ μ“°λ ˆλ“œλ₯Ό μƒμ„±ν•˜λŠ” 것이 더 적은 μ‹œκ°„κ³Ό 곡간 ν•„μš”
  • 단점
    • μ—¬λŸ¬ μ“°λ ˆλ“œκ°€ 같은 ν”„λ‘œμ„ΈμŠ€μ˜ μžμ›μ„ κ³΅μœ ν•˜λ―€λ‘œ 동기화, κ΅μ°©μƒνƒœ λ¬Έμ œλ“€μ„ κ³ λ €ν•΄μ•Ό 함
    • κ΅μ°©μƒνƒœ : 두 μ“°λ ˆλ“œκ°€ μ„œλ‘œ ν•„μš”ν•œ μžμ›μ„ μ μœ ν•œ μƒνƒœμ—μ„œ κΈ°λ‹€λ¦¬λŠλΌ 지원이 λ©ˆμΆ°μ§€λŠ” 상황

2. μ“°λ ˆλ“œμ˜ κ΅¬ν˜„κ³Ό μ‹€ν–‰

  • κ΅¬ν˜„ λ‚΄μš©μ€ run() λ©”μ„œλ“œμ˜ λͺΈν†΅μ— κ΅¬ν˜„
  • Thread 클래슀λ₯Ό 상속
  class MyThread extends Thread{
    public void run(){
      // κ΅¬ν˜„ λ‚΄μš©
    }
  }
  • Ruunnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„
    • λ‹€λ₯Έ 클래슀λ₯Ό 상속받을 수 μžˆμœΌλ―€λ‘œ 이 방법을 더 μ„ ν˜Έ
  class MyThread implements Runnable{
    public void run(){
      // κ΅¬ν˜„ λ‚΄μš©
    }
  }
  • 두 방식은 μΈμŠ€ν„΄μŠ€ 생성 방식이 닀름
    • Thread 클래슀λ₯Ό μƒμ†λ°›λŠ” κ²½μš°μ—” new μ—°μ‚°μžλ‘œ 생성
    • Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 경우 new Thread() μƒμ„±μžμ˜ λ§€κ°œλ³€μˆ˜λ‘œ μ œκ³΅ν•΄μ•Ό 함
  • μ“°λ ˆλ“œ λ‚΄λΆ€ μ½”λ“œμ—μ„œ run 호좜 μ‹œ Runnable의 run()을 ν˜ΈμΆœν•˜κ²Œ ν•΄λ†¨μœΌλ―€λ‘œ run() λ©”μ†Œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”© ν•  ν•„μš”κ°€ μ—†μŒ
  • 단 Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ κ²½μš°μ—” Thread 클래슀의 λ©”μ„œλ“œλ₯Ό 직접 ν˜ΈμΆœν•  순 μ—†μŒ
    • 제곡된 static currentThread()λ₯Ό ν˜ΈμΆœν•˜μ—¬ μ“°λ ˆλ“œμ— λŒ€ν•œ μ°Έμ‘°λ₯Ό 가져와야 함
    • ex) Thread의 이름을 μ•Œκ³  싢을 땐 Thread.currentThread().getName() 호좜
  • μ“°λ ˆλ“œμ˜ 이름은 μƒμ„±μž 및 λ©”μ„œλ“œλ‘œ λ³€κ²½ κ°€λŠ₯, 지정을 μ•ˆ ν•˜λ©΄ Thread-번호

μ“°λ ˆλ“œμ˜ μ‹€ν–‰ - start()

  • run()을 κ΅¬ν˜„ν–ˆλ‹€κ³  μ“°λ ˆλ“œκ°€ μ‹€ν–‰λ˜λŠ” 것이 μ•„λ‹˜
  • start()둜 μ“°λ ˆλ“œλ₯Ό ν˜ΈμΆœν•΄μ•Όλ§Œ μ‹€ν–‰
    • μ‹€ν–‰λ˜κΈ°λ³΄λ‹¨ μ‹€ν–‰ λŒ€κΈ°λ‘œ λ°”λ€Œκ³  μžμ‹ μ˜ μ°¨λ‘€κ°€ λ˜μ–΄μ•Ό μ‹€ν–‰
  • ν•œ 번 μ’…λ£Œλœ μ“°λ ˆλ“œλŠ” λ‹€μ‹œ μ‹€ν–‰ν•  수 μ—†μŒ
    • ν•œ 번 더 μž‘μ—…μ„ μˆ˜ν–‰ν•˜κΈ° μœ„ν•΄μ„  new μƒμ„±μžλ‘œ μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό 생성 ν›„ μ‹€ν–‰

3.start()와 run()

  • start()λŠ” μƒˆλ‘œμš΄ μ“°λ ˆλ“œκ°€ μž‘μ—…μ„ μ‹€ν–‰ν•˜λŠ”λ° ν•„μš”ν•œ 호좜 μŠ€νƒμ„ 생성 ν›„ run()을 호좜
  • 두 개 μ΄μƒμ˜ 호좜 μŠ€νƒμ΄ μ‘΄μž¬ν•  땐 μŠ€μΌ€μ€„λŸ¬κ°€ μ •ν•œ μˆœμ„œμ— μ˜ν•΄μ„œ κ΅λŒ€λ‘œ μ‹€ν–‰
    • 호좜 μŠ€νƒμ˜ κ°€μž₯ μœ„μ— μžˆλŠ” λ©”μ„œλ“œκ°€ μ‹€ν–‰ (λ‚˜λ¨Έμ§€ λ©”μ„œλ“œλŠ” λŒ€κΈ°)
    • 주어진 μ‹œκ°„ λ‚΄λ‘œ μž‘μ—…μ„ λ§ˆμΉ˜μ§€ λͺ»ν•œλ‹€λ©΄ μžμ‹ μ˜ μ°¨λ‘€κ°€ λŒμ•„μ˜¬ λ•ŒκΉŒμ§€ λŒ€κΈ°

main μ“°λ ˆλ“œ

  • main λ©”μ„œλ“œμ˜ μž‘μ—… λ˜ν•œ μ“°λ ˆλ“œκ°€ μ‹€ν–‰ -> main μ“°λ ˆλ“œλΌκ³  뢀름
    • ν”„λ‘œμ„ΈμŠ€κ°€ μ΅œμ†Œλ‘œ ν•„μš”ν•œ μ“°λ ˆλ“œ
  • main μ“°λ ˆλ“œλŠ” μ‚¬μš©μž μ“°λ ˆλ“œμ΄λ©° μ‹€ν–‰ 쀑인 μ‚¬μš©μž μ“°λ ˆλ“œκ°€ ν•˜λ‚˜λ„ 없을 λ•Œ ν”„λ‘œκ·Έλž¨μ€ μ’…λ£Œ
  • ν•œ μ“°λ ˆλ“œμ—μ„œ μ˜ˆμ™Έ λ°œμƒ μ’…λ£Œ μ‹œ λ‹€λ₯Έ μ“°λ ˆλ“œμ—λŠ” 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠμŒ
  • start()κ°€ μ•„λ‹Œ run() 호좜 μ‹œ μ“°λ ˆλ“œκ°€ μƒμ„±λ˜μ§€ μ•Šκ³  run() 호좜 ν›„ 호좜 μŠ€νƒμ— μŒ“μž„

4. μ‹±κΈ€μ“°λ ˆλ“œμ™€ λ©€ν‹°μ“°λ ˆλ“œ

두 개의 μž‘μ—…μ„ ν•˜λ‚˜μ˜ μ“°λ ˆλ“œλ‘œ μ²˜λ¦¬ν•˜λŠ” κ²½μš°μ™€ 두 개의 μ“°λ ˆλ“œλ‘œ μ²˜λ¦¬ν•˜λŠ” 경우

  • CPUλ§Œμ„ μ‚¬μš©ν•˜λŠ” μ‹±κΈ€ 코어에선 λ©€ν‹°μ“°λ ˆλ“œ 보닀 μ‹±κΈ€ μ“°λ ˆλ“œλ‘œ ν”„λ‘œκ·Έλž˜λ° ν•˜λŠ” 것이 효율적
    • 처리 μ‹œκ°„μ€ λ™μΌν•˜κ²Œ κ±Έλ¦¬μ§€λ§Œ λ©€ν‹°μ“°λ ˆλ“œλŠ” μ»¨ν…μŠ€νŠΈ μŠ€μœ„μΉ­μ˜ μ‹œκ°„λ„ μΆ”κ°€λ˜κ³  ν•œ μ“°λ ˆλ“œκ°€ λ‹€λ₯Έ μ“°λ ˆλ“œμ˜ 좜λ ₯이 λλ‚˜κΈ°λ₯Ό κΈ°λ‹€λ €μ•Ό ν•˜λ―€λ‘œ 더 였래 κ±Έλ¦°λ‹€.
    • μ»¨ν…μŠ€νŠΈ μŠ€μœ„μΉ­ μ‹œ λ‹€μŒμ— μ‹€ν–‰ν•΄μ•Ό ν•  μœ„μΉ˜μΈ PC λ“±μ˜ 정보λ₯Ό μ €μž₯ν•˜κ³  μ½μ–΄μ˜¨λ‹€.
    • ν”„λ‘œμ„ΈμŠ€ μ»¨ν…μŠ€νŠΈ μŠ€μœ„μΉ­λ³΄λ‹¨ μ“°λ ˆλ“œ μ»¨ν…μŠ€νŠΈ μŠ€μœ„μΉ­μ΄ 더 적은 μ‹œκ°„μ΄ μ†Œμš”λœλ‹€.
  • μ‹±κΈ€ 코어일 λ•Œμ™€λŠ” λ‹€λ₯΄κ²Œ λ©€ν‹° μ½”μ–΄ 일 λ•ŒλŠ” 두 μ“°λ ˆλ“œκ°€ μˆ˜ν–‰λ  수 μžˆμœΌλ―€λ‘œ κ²ΉμΉ˜λŠ” 뢀뢄이 λ°œμƒ
    • ν™”λ©΄ λ“±μ˜ μžμ›μ„ 놓고 μ“°λ ˆλ“œκ°€ 경쟁
  • μ‹€ν–‰ 쀑인 ν”„λ‘œμ„ΈμŠ€λŠ” 이 OS ν”„λ‘œμ„ΈμŠ€ μŠ€μΌ€μ€„λŸ¬μ˜ 영ν–₯을 λ°›μŒ
    • JVM이 μ“°λ ˆλ“œ μŠ€μΌ€μ€„λŸ¬λ‘œ μ“°λ ˆλ“œμ˜ μ‹€ν–‰ μˆœμ„œ 및 μ‹€ν–‰ μ‹œκ°„μ΄ κ²°μ •λ˜λŠ” κ²ƒμ²˜λŸΌ ν”„λ‘œμ„ΈμŠ€λ„ OS의 ν”„λ‘œμ„ΈμŠ€ μŠ€μΌ€μ€„λŸ¬λ‘œ κ²°μ •
    • μžλ°”λŠ” OS λ…λ¦½μ μ΄μ§€λ§Œ μ‹€μ œλ‘œ μ“°λ ˆλ“œλŠ” OS에 쒅속적
  • 두 μ“°λ ˆλ“œκ°€ μ„œλ‘œ λ‹€λ₯Έ μžμ›μ„ μ‚¬μš©ν•˜λŠ” κ²½μš°μ—λŠ” λ©€ν‹° μ“°λ ˆλ“œ ν”„λ‘œμ„ΈμŠ€κ°€ 더 효율적
    • 데이터λ₯Ό μž…λ ₯λ°›λŠ” μž‘μ—…, λ„€νŠΈμ›Œν¬λ‘œ νŒŒμΌμ„ μ£Όκ³ λ°›λŠ” μž‘μ—… λ“±λ“± μ™ΈλΆ€κΈ°κΈ°μ™€μ˜ μž…μΆœλ ₯이 ν•„μš”ν•  λ•Œ
    • μ‹±κΈ€ μ“°λ ˆλ“œμ—μ„œλŠ” μ™ΈλΆ€μ˜ μž…λ ₯을 κΈ°λ‹€λ¦¬λŠ” λ™μ•ˆ μ•„λ¬΄λŸ° μž‘μ—…λ„ ν•  수 μ—†μŒ
    • 두 개의 μ“°λ ˆλ“œμ—μ„œλŠ” μ‚¬μš©μžμ˜ μž…λ ₯을 κΈ°λ‹€λ¦¬λŠ” λ™μ•ˆ λ‹€λ₯Έ μ“°λ ˆλ“œκ°€ μž‘μ—…μ„ 처리

5. μ“°λ ˆλ“œμ˜ μš°μ„ μˆœμœ„

  • μš°μ„ μˆœμœ„ 값에 따라 μ“°λ ˆλ“œκ°€ μ–»λŠ” μ‹€ν–‰ μ‹œκ°„μ΄ 달라짐

μ“°λ ˆλ“œμ˜ μš°μ„ μˆœμœ„ μ§€μ •ν•˜κΈ°

  • μš°μ„ μˆœμœ„μ˜ λ²”μœ„λŠ” 1~10이며 μˆ«μžκ°€ λ†’μ„μˆ˜λ‘ μš°μ„ μˆœμœ„κ°€ 높아짐
  • μ“°λ ˆλ“œλ₯Ό μƒμ„±ν•œ μ“°λ ˆλ“œλ‘œλΆ€ν„° μš°μ„ μˆœμœ„λ₯Ό μƒμ†λ°›μŒ
    • main λ©”μ„œλ“œλ₯Ό μˆ˜ν–‰ν•˜λŠ” μ“°λ ˆλ“œλŠ” μš°μ„ μˆœμœ„κ°€ 5
  • void setPriority(int newPriority) : μ“°λ ˆλ“œμ˜ μš°μ„ μˆœμœ„λ₯Ό μ§€μ •ν•œ κ°’μœΌλ‘œ λ³€κ²½
  • int getPriority() : μ“°λ ˆλ“œμ˜ μš°μ„ μˆœμœ„λ₯Ό λ°˜ν™˜
  • λ©€ν‹° μ½”μ–΄μ—μ„œλŠ” μ“°λ ˆλ“œμ˜ μš°μ„ μˆœμœ„μ— λ”°λ₯Έ 차이가 거의 μ—†μŒ
    • κ·Έμ € 더 λ§Žμ€ μ‹€ν–‰ μ‹œκ°„κ³Ό μ‹€ν–‰ 기회λ₯Ό κ°–κ²Œ 될 것이라고 κΈ°λŒ€ν•  μˆ˜λ°–μ— μ—†μŒ
    • PriorityQueueλ₯Ό μ‚¬μš©ν•˜μ—¬ μš°μ„ μˆœμœ„κ°€ 높은 μž‘μ—…μ„ λ¨Όμ € μ²˜λ¦¬ν•˜λ„λ‘ κ΅¬ν˜„ν•˜λŠ” 게 더 λ‚˜μ„ μˆ˜λ„ 있음

6. μ“°λ ˆλ“œ κ·Έλ£Ή(thread group)

  • μ“°λ ˆλ“œ 그룹은 μ„œλ‘œ κ΄€λ ¨λœ μ“°λ ˆλ“œλ₯Ό 그룹으둜 닀루기 μœ„ν•œ 것
    • 폴더λ₯Ό μƒμ„±ν•΄μ„œ κ΄€λ ¨λœ νŒŒμΌμ„ κ΄€λ¦¬ν•˜λŠ” 것과 λΉ„μŠ·ν•¨
  • μ“°λ ˆλ“œ 그룹에 λ‹€λ₯Έ μ“°λ ˆλ“œ 그룹을 포함 μ‹œν‚¬ 수 있음
  • μ“°λ ˆλ“œ 그룹은 λ³΄μ•ˆμƒμ˜ 이유둜 λ„μž…
    • μžμ‹ μ΄ μ†ν•œ μ“°λ ˆλ“œ κ·Έλ£Ήμ΄λ‚˜ ν•˜μœ„ μ“°λ ˆλ“œ 그룹만 λ³€κ²½ν•˜λ„λ‘ ν•˜κΈ° μœ„ν•΄
  • ThreadGroup을 μ‚¬μš©ν•˜μ—¬ 생성
  • λͺ¨λ“  μ“°λ ˆλ“œλŠ” λ°˜λ“œμ‹œ μ“°λ ˆλ“œ 그룹에 ν¬ν•¨λ˜μ–΄μ•Ό 함
    • μ“°λ ˆλ“œ 그룹을 μ§€μ •ν•˜λŠ” μƒμ„±μžλ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” μ“°λ ˆλ“œλŠ” μžμ‹ μ„ μƒμ„±ν•œ μ“°λ ˆλ“œμ™€ 같은 그룹에 μ†ν•˜κ²Œ 됨
    • κ·ΈλŸ¬λ―€λ‘œ μš°λ¦¬κ°€ λ§Œλ“œλŠ” λͺ¨λ“  μ“°λ ˆλ“œλŠ” main μ“°λ ˆλ“œ 그룹의 ν•˜μœ„
  • JVM은 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰ μ‹œ mainκ³Ό systemμ΄λΌλŠ” μ“°λ ˆλ“œ κ·Έλ£Ή 생성
    • main λ©”μ„œλ“œλ₯Ό μˆ˜ν–‰ν•˜λŠ” μ“°λ ˆλ“œλŠ” main 그룹에 속함
    • 가비지 μ»¬λ ‰μ…˜μ„ μˆ˜ν–‰ν•˜λŠ” Finalizer μ“°λ ˆλ“œλŠ” system 그룹에 속함
  • ThreadGroup getThreadGroup() : μ“°λ ˆλ“œ μžμ‹ μ΄ μ†ν•œ κ·Έλ£Ή λ°˜ν™˜
  • void uncaughtException(Tread t, Throwable e) : μ“°λ ˆλ“œ 그룹의 μ“°λ ˆλ“œκ°€ μ²˜λ¦¬λ˜μ§€ μ•ŠλŠ” μ˜ˆμ™Έμ— μ˜ν•΄ 싀행이 μ’…λ£Œλ˜μ—ˆμ„ λ•Œ, JVM에 μ˜ν•΄ 이 λ©”μ„œλ“œκ°€ μžλ™μœΌλ‘œ 호좜

7. 데λͺ¬ μ“°λ ˆλ“œ(daemon thread)

  • 일반 μ“°λ ˆλ“œμ˜ μž‘μ—…μ„ λ•λŠ” 보쑰적인 μ—­ν•  μˆ˜ν–‰
    • 일반 μ“°λ ˆλ“œκ°€ λͺ¨λ‘ μ’…λ£Œλ  μ‹œ 데λͺ¬ μ“°λ ˆλ“œλ„ μžλ™ μ’…λ£Œ
    • μ˜ˆλ‘œλŠ” 가비지 컬렉터, μžλ™ μ €μž₯, ν™”λ©΄ μžλ™κ°±μ‹  λ“±λ“±
  • νŠΉμ • 쑰건이 만쑱되면 μˆ˜ν–‰ ν›„ λ‹€μ‹œ λŒ€κΈ°
  • μ‹€ν–‰ν•˜κΈ° μ „ setDaemon(true)λ₯Ό 호좜
    • μ“°λ ˆλ“œλ₯Ό 데λͺ¬ μ“°λ ˆλ“œλ‚˜ μ‚¬μš©μž μ“°λ ˆλ“œλ‘œ λ³€κ²½ν•˜λŠ” λ©”μ„œλ“œ
    • λ°˜λ“œμ‹œ start()λ₯Ό ν˜ΈμΆœν•˜κΈ° 전에 μ‹€ν–‰μ‹œν‚¬ 것
  • 데λͺ¬ μ“°λ ˆλ“œκ°€ μƒμƒν•œ μ“°λ ˆλ“œλŠ” μžλ™μœΌλ‘œ 데λͺ¬ μ“°λ ˆλ“œκ°€ 됨
  • boolean isDaemon() λ©”μ„œλ“œλ‘œ μ“°λ ˆλ“œκ°€ 데λͺ¬ μ“°λ ˆλ“œμΈμ§€ 확인
  • ν”„λ‘œκ·Έλž¨μ„ μ‹œμž‘ μ‹œ 보쑰 μž‘μ—…μ„ ν•˜λŠ” λ§Žμ€ 데λͺ¬ μ“°λ ˆλ“œλ“€μ΄ 싀행됨
    • 각자 system μ“°λ ˆλ“œ κ·Έλ£Ή, main μ“°λ ˆλ“œ 그룹에 μ†ν•΄μžˆμŒ

8. μ“°λ ˆλ“œμ˜ μ‹€ν–‰ μ œμ–΄

  • μ“°λ ˆλ“œμ˜ μƒνƒœ
    • NEW : μ“°λ ˆλ“œκ°€ μƒμ„±λ˜κ³  start() 호좜되기 μ „
    • RUNNALBE : μ‹€ν–‰ 쀑 or μ‹€ν–‰ κ°€λŠ₯ μƒνƒœ
    • BLOCKED : 동기화 λΈ”λŸ­μ— μ˜ν•΄ μΌμ‹œμ •μ§€λœ μƒνƒœ
    • WAITING, TIMED_WAITING : μ“°λ ˆλ“œμ˜ μž‘μ—…μ΄ μ’…λ£Œλ˜μ§€λŠ” μ•Šμ•˜μ§€λ§Œ μ‹€ν–‰ κ°€λŠ₯ν•˜μ§€ μ•Šμ€ μΌμ‹œμ •μ§€ μƒνƒœ (TIME_WATING은 μΌμ‹œμ •μ§€μ‹œκ°„μ΄ 지정)
    • TERMINATED : μ“°λ ˆλ“œμ˜ μž‘μ—…μ΄ μ’…λ£Œλœ μƒνƒœ
  • μ“°λ ˆλ“œμ˜ 생성뢀터 μ†Œλ©Έ κ³Όμ •
    • start()λ₯Ό ν˜ΈμΆœν•˜λ©΄ μ‹€ν–‰ λŒ€κΈ°μ—΄μ— μ €μž₯ ν›„ 자기 μ°¨λ‘€ κΈ°λ‹€λ¦Ό (μ‹€ν–‰ λŒ€κΈ°μ—΄μ€ 큐와 같은 ꡬ쑰)
    • μžμ‹ μ˜ μ°¨λ‘€κ°€ 되면 μ‹€ν–‰μƒνƒœ
    • 주어진 μ‹€ν–‰ 기간이 λ‹€λ˜λŠ” κ²½μš°λ‚˜ yield()λ₯Ό λ§Œλ‚˜λ©΄ μ‹€ν–‰ λŒ€κΈ° μƒνƒœλ‘œ λ‹€μ‹œ μ‹€ν–‰ λŒ€κΈ°μ—΄λ‘œ 듀어감
    • μ‹€ν–‰ 쀑 suspend(), sleep(), wait(), join(), I/O block에 μ˜ν•΄ μΌμ‹œμ •μ§€κ°€ 될 수 있음
    • μ§€μ •λœ μΌμ‹œμ •μ§€ μ‹œκ°„μ΄ λ‹€ λ˜λŠ” 경우, notify(), resume(), interrupt()κ°€ 호좜되면 μΌμ‹œμ •μ§€λ₯Ό λ²—μ–΄λ‚˜μ„œ λ‹€μ‹œ μ‹€ν–‰ λŒ€κΈ°μ—΄λ‘œ 듀어감
    • 싀행을 λͺ¨λ‘ λ§ˆμΉ˜λŠ” 경우, stop()을 ν˜ΈμΆœν•˜λŠ” 경우 μ“°λ ˆλ“œ μ†Œλ©Έ

sleep(long millis) - 일정 κΈ°κ°„ λ™μ•ˆ μ“°λ ˆλ“œλ₯Ό λ©ˆμΆ”κ²Œ 함

  • 두 번째 νŒŒλΌλ―Έν„°λ₯Ό 넣을 μ‹œ λ‚˜λ…Έμ„Έμ»¨λ“œκΉŒμ§€ 지정 κ°€λŠ₯
  • static λ©”μ„œλ“œ
    • μ°Έμ‘°λ³€μˆ˜μ™€ 상관 없이 ν˜„μž¬ μ‹€ν–‰ 쀑인 μ“°λ ˆλ“œμ— λŒ€ν•΄ μž‘λ™
    • μ°Έμ‘°λ³€μˆ˜λ₯Ό μ΄μš©ν•˜κΈ°λ³΄λ‹¨ Thread.sleep()으둜 μ‚¬μš©ν•  것
  • μ‹œκ°„μ΄ λ‹€ λ˜κ±°λ‚˜ interrupt()λ₯Ό ν˜ΈμΆœν•΄μ•Ό μž μ—μ„œ κΉ¨μ–΄λ‚˜ μ‹€ν–‰ λŒ€κΈ° μƒνƒœλ‘œ λ°”λ€œ
  • 항상 try-catch 문으둜 μ˜ˆμ™Έ 처리 ν•„μš”
    • InterruptedException은 λŸ°νƒ€μž„ μ˜ˆμ™Έκ°€ μ•„λ‹ˆλ―€λ‘œ
    • try-catch 문을 λ‹€λ£¨λŠ” λ©”μ„œλ“œλ₯Ό λ§Œλ“€μ–΄μ„œ μ‚¬μš©ν•˜κΈ°λ„ 함

interrupt()와 interrupted() - μ“°λ ˆλ“œμ˜ μž‘μ—…μ„ μ·¨μ†Œν•œλ‹€.

  • interrupt()λŠ” μ“°λ ˆλ“œμ—κ²Œ μž‘μ—…μ„ λ©ˆμΆ”λΌκ³  μš”μ²­
    • μ“°λ ˆλ“œλ₯Ό κ°•μ œλ‘œ μ’…λ£Œμ‹œν‚€μ§€λŠ” λͺ»ν•¨
    • μΈμŠ€ν„΄μŠ€ λ³€μˆ˜μΈ interrupted의 μƒνƒœλ₯Ό λ³€κ²½ν•˜λŠ” 것뿐 (true둜)
  • interrupted() λ©”μ„œλ“œλ‘œ μ“°λ ˆλ“œμ— λŒ€ν•΄ interruptκ°€ ν˜ΈμΆœλ˜μ—ˆλŠ”μ§€ 확인 κ°€λŠ₯ (interrupted의 μƒνƒœλ₯Ό ν˜ΈμΆœν•΄μ„œ)
    • κ·Έ ν›„ interrupted의 μƒνƒœλ₯Ό false둜 λ³€κ²½
    • isInterrupted()λŠ” μ“°λ ˆλ“œμ˜ interruptedλ₯Ό ν™•μΈν•˜λŠ” 것인 λ™μΌν•˜μ§€λ§Œ μƒνƒœ λ³€κ²½ X
  • sleep(), wait(), join()μ—μ„œ interrupt() 호좜 μ‹œ μ‹€ν–‰ λŒ€κΈ° μƒνƒœλ‘œ λ°”λ€œ
    • λ©ˆμΆ°μžˆμ„ λ•Œ interrupt()λ₯Ό ν˜ΈμΆœν•˜λ©΄ InterruptedException이 λ°œμƒλ˜κ³  μ“°λ ˆλ“œμ˜ interrupted의 μƒνƒœλŠ” false둜 μžλ™ μ΄ˆκΈ°ν™”

suspend(), resume(), stop()

  • suspend()λŠ” sleep()처럼 μ“°λ ˆλ“œλ₯Ό λ©ˆμΆ”κ²Œ 함
    • resume()을 ν˜ΈμΆœν•˜λ©΄ λ‹€μ‹œ μ‹€ν–‰ λŒ€κΈ° μƒνƒœ
    • stop()은 ν˜ΈμΆœλ˜λŠ” μ¦‰μ‹œ μ“°λ ˆλ“œκ°€ μ’…λ£Œ
  • suspend()와 stop()이 κ΅μ°©μƒνƒœλ₯Ό μΌμœΌν‚€κΈ° μ‰½κ²Œ μž‘μ„±λ˜μ—ˆμœΌλ―€λ‘œ μ‚¬μš© ꢌμž₯ X
    • deprecated λ˜μ–΄ 있음
  • suspend와 stop이 λ™μž‘ν•˜μ§€ μ•Šμ„ μ‹œ λ³€μˆ˜ μ•žμ— volatile μ„ μ–Έ

yield() - λ‹€λ₯Έ μ“°λ ˆλ“œμ—κ²Œ μ–‘λ³΄ν•œλ‹€.

  • yield()λŠ” μ“°λ ˆλ“œ μžμ‹ μ—κ²Œ 주어진 μ‹€ν–‰ μ‹œκ°„μ„ λ‹€μŒ μ°¨λ‘€μ˜ μ“°λ ˆλ“œμ—κ²Œ 양보
    • 할당받은 μ‹€ν–‰ μ‹œκ°„μ„ μ‚¬μš©ν•˜λ˜ 쀑 yield()λ₯Ό λ§Œλ‚˜λ©΄ λ‚˜λ¨Έμ§€ μ‹€ν–‰ μ‹œκ°„μ€ ν¬κΈ°ν•˜κ³  λ‹€μ‹œ μ‹€ν–‰ λŒ€κΈ° μƒνƒœ
  • ν”„λ‘œκ·Έλž¨μ˜ 응닡성을 높이고 효율적인 싀행을 μœ„ν•΄ μ‚¬μš©
    • μ“°λ ˆλ“œκ°€ 싀행을 λ©ˆμΆ”κ²Œ ν•œ μƒνƒœμ—μ„œ while이 λ°˜λ³΅λœλ‹€λ©΄ λ°”μœ λŒ€κΈ° μƒνƒœ(busy wating)둜 μ‹€ν–‰ μ‹œκ°„μ„ 의미 없이 λ‚­λΉ„
    • μ΄λ•Œ yield()λ₯Ό ν˜ΈμΆœν•΄μ„œ 남은 μ‹œκ°„μ„ while

join() - λ‹€λ₯Έ μ“°λ ˆλ“œμ˜ μž‘μ—…μ„ κΈ°λ‹€λ¦°λ‹€.

  • μ“°λ ˆλ“œ μžμ‹ μ˜ ν•˜λ˜ μž‘μ—…μ„ μž μ‹œ λ©ˆμΆ”κ³  λ‹€λ₯Έ μ“°λ ˆλ“œκ°€ μ§€μ •λœ μ‹œκ°„ λ™μ•ˆ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λ„λ‘ ν•  λ•Œ join()을 μ‚¬μš©
  • μ‹œκ°„μ„ 지정할 수 있고 μ§€μ •ν•˜μ§€ μ•ŠμœΌλ©΄ ν•΄λ‹Ή μ“°λ ˆλ“œκ°€ λͺ¨λ‘ 마칠 λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦Ό
  • join()도 interrupt()에 μ˜ν•΄ λ²—μ–΄λ‚  수 있음
    • sleep()κ³Ό λ‹€λ₯Έ 점은 ν˜„μž¬ μ“°λ ˆλ“œκ°€ μ•„λ‹Œ νŠΉμ • μ“°λ ˆλ“œμ— λŒ€ν•΄ λ™μž‘

9. μ“°λ ˆλ“œμ˜ 동기화

  • λ©€ν‹°μ“°λ ˆλ“œ ν”„λ‘œμ„ΈμŠ€λŠ” μ—¬λŸ¬ μ“°λ ˆλ“œκ°€ 같은 ν”„λ‘œμ„ΈμŠ€ λ‚΄μ˜ μžμ›μ„ κ³΅μœ ν•΄μ„œ μž‘μ—…
    • μ„œλ‘œμ˜ μž‘μ—…μ— 영ν–₯을 쀌
    • μž‘μ—…ν•˜λ˜ 곡유 데이터λ₯Ό λ‹€λ₯Έ μ“°λ ˆλ“œκ°€ λ³€κ²½ν•˜λ©΄ μ˜λ„ν•œ 것과 λ‹€λ₯Έ κ²°κ³Όκ°€ λ‚˜μ˜¬ μˆ˜λ„ 있음
    • λ‹€λ₯Έ μ“°λ ˆλ“œμ—κ²Œ 방해받지 μ•Šλ„λ‘ λ‚˜μ˜¨ 것이 μž„κ³„ μ˜μ—­(critical section), 락(lock)
    • 곡유 데이터λ₯Ό μ‚¬μš©ν•˜λŠ” μ½”λ“œ μ˜μ—­μ„ μž„κ³„ μ˜μ—­μœΌλ‘œ 지정
    • 락을 νšλ“ν•œ 단 ν•˜λ‚˜μ˜ μ“°λ ˆλ“œλ§Œ μž„κ³„ μ˜μ—­ λ‚΄μ˜ μ½”λ“œλ₯Ό μˆ˜ν–‰ν•  수 있게 함
    • μ΄λ ‡κ²Œ λ‹€λ₯Έ μ“°λ ˆλ“œκ°€ μž‘μ—…μ— 간섭을 λͺ» ν•˜κ²Œ ν•˜λŠ” 것을 μ“°λ ˆλ“œμ˜ 동기화(synchronization)이라고 뢀름

9.1 synchronizedλ₯Ό μ΄μš©ν•œ 동기화

  • λ™κΈ°ν™”μ˜ 두 가지 방식
    • λ©”μ„œλ“œ 전체λ₯Ό μž„κ³„ μ˜μ—­μœΌλ‘œ 지정
    • νŠΉμ •ν•œ μ˜μ—­μ„ μž„κ³„ μ˜μ—­μœΌλ‘œ 지정 (μ΄λ•Œμ˜ λΈ”λŸ­μ„ synchronized λΈ”λŸ­μ΄λΌκ³  뢀름)
    • λ‘˜ λ‹€ lock을 μ–»μ–΄μ•Ό μ ‘κ·Ό κ°€λŠ₯ν•˜κ³  λ²—μ–΄λ‚  μ‹œ lock을 λ°˜λ‚©ν•œλ‹€.
    • λͺ¨λ“  κ°μ²΄λŠ” lock을 ν•˜λ‚˜μ”© 가지고 μžˆλ‹€.
    • λ©”μ„œλ“œ μ „μ²΄μ˜ lock보단 λΈ”λŸ­ λ‹¨μœ„λ³„λ‘œ μž„κ³„ μ˜μ—­μ„ μ΅œμ†Œν™”ν•˜λŠ” 것이 효율적
    • 동기화에 λ“€μ–΄κ°€λŠ” λ³€μˆ˜λ“€μ€ private둜 μ„€μ •ν•  것 (private이 μ•„λ‹ˆλ©΄ 동기화λ₯Ό 해도 κ°’μ˜ 변경을 막을 방법이 μ—†λ‹€.)

9.2 wait()κ³Ό notify()

  • wait()
    • λ™κΈ°ν™”λœ μž„κ³„ μ˜μ—­μ˜ μ½”λ“œλ₯Ό μˆ˜ν–‰ν•˜λ‹€κ°€ 더 이상 μž‘μ—…μ„ 진행할 상황이 μ•„λ‹ˆλ©΄ wait() 호좜 ν›„ 락을 λ°˜λ‚©ν•˜κ³  μ“°λ ˆλ“œλ₯Ό κΈ°λ‹€λ¦¬κ²Œ ν•œλ‹€.
    • λ§€κ°œλ³€μˆ˜λ₯Ό λ„£μœΌλ©΄ μ§€μ •λœ μ‹œκ°„ λ™μ•ˆλ§Œ κΈ°λ‹€λ¦Ό
    • λ§€κ°œλ³€μˆ˜κ°€ 없을 μ‹œ notify()κ°€ 호좜될 λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦Ό
  • notify()
    • 기닀리고 μžˆλŠ” μ“°λ ˆλ“œλ“€μ—κ²Œ 톡지λ₯Ό ν•˜μ—¬ 락을 μ–»μ–΄ μž‘μ—…μ„ 진행할 수 있게 ν•œλ‹€.
    • μ“°λ ˆλ“œλ“€μ€ 객체의 λŒ€κΈ°μ‹€(waiting pool)μ—μ„œ 톡지λ₯Ό κΈ°λ‹€λ¦°λ‹€.
    • ν•΄λ‹Ή 객체의 λŒ€κΈ°μ‹€μ— 있던 λͺ¨λ“  μ“°λ ˆλ“œ μ€‘μ—μ„œ μž„μ˜μ˜ μ“°λ ˆλ“œλ§Œ 톡지λ₯Ό λ°›μŒ
    • notifyAll()은 기닀리고 μžˆλŠ” λͺ¨λ“  μ“°λ ˆλ“œλ“€(호좜된 객체의 waiting pool에 μžˆλŠ”)μ—κ²Œ 톡보, ν•˜μ§€λ§Œ lcok을 얻을 수 μžˆλŠ” μ“°λ ˆλ“œλŠ” 단 ν•˜λ‚˜
  • wait(), notify()λŠ” Object ν΄λž˜μŠ€μ— μ •μ˜ (νŠΉμ • 객체에 λŒ€ν•œ κ²ƒμ΄λ―€λ‘œ)

κΈ°μ•„ ν˜„μƒκ³Ό 경쟁 μƒνƒœ

  • ν•œ μ“°λ ˆλ“œκ°€ 계속 톡지λ₯Ό 받지 λͺ»ν•˜κ³  μ˜€λž«λ™μ•ˆ κΈ°λ‹€λ¦¬κ²Œ λ˜λŠ” ν˜„μƒμ„ κΈ°μ•„(starvation) ν˜„μƒμ΄λΌκ³  함
  • notify() λŒ€μ‹  notifyAll()을 μ‚¬μš©ν•΄μ„œ 막을 수 있음
  • μ—¬λŸ¬ μ“°λ ˆλ“œκ°€ 톡지λ₯Ό λ°›μ•„μ„œ lock에 λŒ€ν•΄ κ²½μŸν•˜λŠ” μƒνƒœλ₯Ό 경쟁 μƒνƒœ(race condtion)
    • 경쟁 μƒνƒœλ₯Ό κ°œμ„ ν•˜κΈ° μœ„ν•΄ μ“°λ ˆλ“œλ₯Ό κ΅¬λ³„ν•΄μ„œ 톡지해야 함 (Lockκ³Ό Condition 이용)

9.3 Lockκ³Ό Condition을 μ΄μš©ν•œ 동기화

  • synchronized λΈ”λŸ­ 외에도 java.util.concurrent.locks νŒ¨ν‚€μ§€μ˜ lcok ν΄λž˜μŠ€λ“€μ„ 이용
    • JDK 1.5μ—μ„œ μΆ”κ°€
  • ReentrantLock : μž¬μ§„μž…μ΄ κ°€λŠ₯ν•œ lock. κ°€μž₯ 일반적인 배타 lock
    • μž¬μ§„μž…μ€ lock을 ν‘Ό λ’€ 좔후에 λ‹€μ‹œ lock을 μ–»μ–΄ 접근을 의미
  • ReentrantReadWriteLock : μ½κΈ°μ—λŠ” 곡유적, μ“°κΈ°μ—λŠ” 배타적인 lock
    • 읽기 lockκ³Ό μ“°κΈ° lock을 제곡
    • 읽기 lock은 μ€‘λ³΅ν•΄μ„œ κ±Έκ³  읽기 μˆ˜ν–‰ κ°€λŠ₯
    • 읽기 lock이 κ±Έλ¦° μƒνƒœμ—μ„œ μ“°κΈ° lock을 κ±°λŠ” 것은 ν—ˆμš© X (λ°˜λŒ€λ„ ν—ˆμš© X)
  • StampedLock : ReentrantLock에 낙관적인 lock의 κΈ°λŠ₯을 μΆ”κ°€
    • lock을 κ±Έκ±°λ‚˜ 해지할 λ•Œ μŠ€νƒ¬ν”„λ₯Ό μ‚¬μš©
    • μŠ€νƒ¬ν”„λŠ” longνƒ€μž…μ˜ μ •μˆ«κ°’
    • 낙관적 읽기 lock은 μ“°κΈ° lock에 μ˜ν•΄ λ°”λ‘œ ν’€λ¦Ό
    • 낙관적 읽기에 μ‹€νŒ¨ν•˜λ©΄ 읽기 lock을 μ–»μ–΄μ„œ λ‹€μ‹œ 읽어 와야 함 (무쑰건 읽기 lock을 걸지 μ•Šκ³  쓰기와 읽기가 μΆ©λŒν•  λ•Œλ§Œ μ“°κΈ°κ°€ λλ‚œ 후에 읽기 lock을 걸음)

ReentrantLock의 μƒμ„±μž

  • μ’…λ₯˜
    • ReentrantLock()
    • ReentrantLock(boolean fair)
  • μƒμ„±μžμ˜ λ§€κ°œλ³€μˆ˜λ₯Ό true둜 μ£Όλ©΄ lock이 풀렸을 λ•Œ κ°€μž₯ 였래 κΈ°λ‹€λ¦° μ“°λ ˆλ“œκ°€ lock을 νšλ“
    • μ–΄λ–€ μ“°λ ˆλ“œκ°€ 였래 κΈ°λ‹€λ ΈλŠ”μ§€ μ—°μ‚° ν•„μš”ν•˜λ―€λ‘œ μ„±λŠ₯ 떨어짐
    • λŒ€λΆ€λΆ„ 곡정함보닀 μ„±λŠ₯을 선택
  • synchronized와 달리 lock ν΄λž˜μŠ€λ“€μ€ μˆ˜λ™μœΌλ‘œ lock을 잠그고 ν•΄μ œν•΄μ•Ό 함 (빼먹지 μ•Šλ„λ‘ 주의)
    • void lock() : lock을 잠금
    • void unlock() : lock을 해지
    • boolean isLocked() : lock이 μž κ²ΌλŠ”μ§€ 확인
    • μ˜ˆμ™Έ λ°œμƒ 및 return 문으둜 λΉ μ Έλ‚˜κ°ˆ 수 μžˆμœΌλ―€λ‘œ try-finally 문으둜 κ°μ‹ΈλŠ” 것이 일반적
  • tryLock : λ‹€λ₯Έ μ“°λ ˆλ“œμ— μ˜ν•΄ lock이 κ±Έλ € 있으면 lock을 μ–»μœΌλ €κ³  기닀리지 μ•Šκ±°λ‚˜ μ§€μ •λœ μ‹œκ°„λ§ŒνΌλ§Œ κΈ°λ‹€λ¦Ό
    • interrupt()에 μ˜ν•΄ μž‘μ—…μ΄ μ·¨μ†Œλ  수 μžˆλ„λ‘ μž‘μ„±λ¨ (InterruptedException λ°œμƒ κ°€λŠ₯)

ReentrantLockκ³Ό Condition

  • 각 μ“°λ ˆλ“œλ₯Ό μœ„ν•œ Condition을 λ§Œλ“€μ–΄μ„œ 각각의 wating poolμ—μ„œ λ”°λ‘œ 기닀리도둝 ν•  수 있음
  • Condotion은 이미 μƒμ„±λœ lockμœΌλ‘œλΆ€ν„° newCondition()을 ν˜ΈμΆœν•΄μ„œ 생성
    • κ·Έ ν›„ await() & signal()을 μ‚¬μš©ν•˜λ©΄ 됨
    • λŒ€μƒμ„ λͺ…ν™•νžˆ ꡬ뢄할 수 있음

9.4 volatile

  • λ©€ν‹° μ½”μ–΄ ν”„λ‘œμ„Έμ„œμ—μ„œλŠ” μ½”μ–΄λ§ˆλ‹€ λ³„λ„μ˜ μΊμ‹œλ₯Ό 가지고 있음
    • μ½”μ–΄λŠ” λ©”λͺ¨λ¦¬μ—μ„œ μ½μ–΄μ˜¨ 값을 μΊμ‹œμ— μ €μž₯ν•˜κ³  μΊμ‹œμ—μ„œ 값을 μ½μ–΄μ„œ μž‘μ—…
    • μΊμ‹œμ— μ €μž₯된 값이 κ°±μ‹ λ˜μ§€ μ•Šμ•„μ„œ λ©”λͺ¨λ¦¬μ— μ €μž₯된 값이 λ‹€λ₯Έ 경우 λ°œμƒ
    • μ΄λ•Œ volatile을 λ³€μˆ˜ μ•žμ— 뢙이면 μΊμ‹œκ°€ μ•„λ‹Œ λ©”λͺ¨λ¦¬μ—μ„œ μ½”μ–΄κ°€ 값을 μ½μ–΄μ˜΄
  • volatile을 λΆ™μ΄λŠ” λŒ€μ‹ μ— synchronized λΈ”λŸ­μ„ μ‚¬μš©ν•΄λ„ 같은 효과
    • μ“°λ ˆλ“œκ°€ synchronized λΈ”λŸ­μœΌλ‘œ λ“€μ–΄κ°ˆ λ•Œμ™€ λ‚˜μ˜¬ λ•Œ μΊμ‹œμ™€ λ©”λͺ¨λ¦¬ κ°„μ˜ 동기화가 이루어지기 λ•Œλ¬Έ

volatile둜 longκ³Ό double을 μ›μžν™”

  • JVM이 데이터λ₯Ό ν•œ λ²ˆμ— μ²˜λ¦¬ν•˜λŠ” μ΅œμ†Œ λ‹¨μœ„λŠ” 4byte
    • 4byte보닀 큰 longκ³Ό double νƒ€μž…(8byte)λŠ” λ³€μˆ˜λ₯Ό μ½λŠ” 과정에 λ‹€λ₯Έ μ“°λ ˆλ“œκ°€ 끼어듀 여지가 있음 (ν•˜λ‚˜μ˜ λͺ…λ Ήμ–΄λ‘œ 값을 μ“°κ±°λ‚˜ 읽을 수 μ—†μœΌλ―€λ‘œ)
    • λ³€μˆ˜λ₯Ό μ„ μ–Έν•  λ•Œ volatile을 뢙이면 μ΄λŸ¬ν•œ 문제 ν•΄κ²°
  • volatileλŠ” ν•΄λ‹Ή λ³€μˆ˜μ— λŒ€ν•œ 읽기, μ“°κΈ°λ₯Ό μ›μžν™”
    • μƒμˆ˜λŠ” λ³€ν•˜μ§€ μ•ŠλŠ” κ°’μ΄λ―€λ‘œ tread-safeμž„μœΌλ‘œ volatile을 뢙일 ν•„μš”κ°€ μ—†κ³  뢙일 μˆ˜λ„ μ—†μŒ
    • λ³€μˆ˜μ˜ μ½κΈ°λ‚˜ μ“°κΈ°λ₯Ό μ›μžν™”ν•  뿐 동기화가 μ•„λ‹ˆλΌλŠ” 점에 주의(ν•„μš”ν•œ λ©”μ„œλ“œλ‚˜ λΈ”λŸ­μ€ 동기화λ₯Ό ν•΄μ•Ό ν•œλ‹€.)

9.5 fork & join ν”„λ ˆμž„μ›

  • λ©€ν‹° μ½”μ–΄λ₯Ό 잘 ν™œμš©ν•  수 μžˆλŠ” λ©€ν‹° μ“°λ ˆλ“œ ν”„λ‘œκ·Έλž˜λ°μ΄ μ€‘μš”ν•΄μ§
    • JDK 1.7λΆ€ν„° fork & join ν”„λ ˆμž„μ›μ„ μΆ”κ°€
    • ν•˜λ‚˜μ˜ μž‘μ—…μ„ μž‘μ€ λ‹¨μœ„λ‘œ λ‚˜λˆ μ„œ μ—¬λŸ¬ μ“°λ ˆλ“œμ—μ„œ λ™μ‹œμ— μ²˜λ¦¬ν•˜λŠ” 것을 μ‰½κ²Œ λ§Œλ“€μ–΄μ€Œ
  • 두 클래슀 쀑 ν•˜λ‚˜λ₯Ό μƒμ†λ°›μ•„μ„œ κ΅¬ν˜„
    • RecursiveAction : λ°˜ν™˜κ°’μ΄ μ—†λŠ” μž‘μ—… κ΅¬ν˜„
    • RecursiveTask : λ°˜ν™˜κ°’μ΄ μžˆλŠ” μž‘μ—…μ„ κ΅¬ν˜„
  • compute() 좔상 λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•΄μ•Ό 함
    • run()κ³Ό start()의 κ΄€κ³„μ²˜λŸΌ invoke()둜 ν˜ΈμΆœμ„ ν•΄μ•Ό μž‘μ—…μ„ μ‹€ν–‰
  • fork & join ν”„λ ˆμž„μ›μ—μ„œ μ œκ³΅ν•˜λŠ” ForkJoinPoolμ΄λΌλŠ” μ“°λ ˆλ“œν’€μ—μ„œ μ“°λ ˆλ“œλ₯Ό μ‚¬μš©
    • μ§€μ •λœ 수의 μ“°λ ˆλ“œλ₯Ό 미리 μƒμ„±ν•œ λ’€ λ°˜λ³΅ν•΄μ„œ μž¬μ‚¬μš© κ°€λŠ₯
    • 반볡 생성 μ–΅μ œ, μ λ‹Ήν•œ μ“°λ ˆλ“œ 생성 (μ„±λŠ₯을 μ €ν•˜μ‹œν‚¬ μ •λ„λ‘œ μ“°λ ˆλ“œλ₯Ό λ§Œλ“€μ§€ μ•ŠμŒ)
    • 각 μ“°λ ˆλ“œλŠ” μžμ‹ μ˜ μž‘μ—… 큐에 λ‹΄κΈ΄ μž‘μ—… μˆœμ„œλŒ€λ‘œ 처리

λ‹€λ₯Έ μ“°λ ˆλ“œμ˜ μž‘μ—… 훔쳐 였기

  • μžμ‹ μ˜ μž‘μ—… 큐가 λΉ„μ–΄μžˆλŠ” μ“°λ ˆλ“œλŠ” λ‹€λ₯Έ μ“°λ ˆλ“œμ˜ μž‘μ—… νμ—μ„œ μž‘μ—…μ„ κ°€μ Έμ™€μ„œ μˆ˜ν–‰
  • μ“°λ ˆλ“œν’€μ— μ˜ν•΄ μžλ™μ μœΌλ‘œ 이루어짐
  • μ—¬λŸ¬ μ“°λ ˆλ“œκ°€ 골고루 μž‘μ—…μ„ λ‚˜λˆ„μ–΄ 처리

fork()와 join()

  • fork() : ν•΄λ‹Ή μž‘μ—…μ„ μ“°λ ˆλ“œ ν’€μ˜ μž‘μ—… 큐에 λ„£λŠ” 비동기 λ©”μ„œλ“œ
    • 비동기 λ©”μ„œλ“œλŠ” λ‹€λ₯Έ μ“°λ ˆλ“œμ—κ²Œ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λ„λ‘ μ§€μ‹œλ§Œ ν•˜κ³  κ²°κ³Όλ₯Ό 기닀리지 μ•ŠμŒ
  • join() : ν•΄λ‹Ή μž‘μ—…μ˜ μˆ˜ν–‰μ΄ 끝날 λ•ŒκΉŒμ§€ κΈ°λ‹€λ Έλ‹€κ°€ μˆ˜ν–‰μ΄ λλ‚˜λ©΄ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜λŠ” 동기 λ©”μ„œλ“œ