HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🤩
개발
/
Java
Java
/
💯
Java 기본
/활용 (API)/
⛸️
multi threading
⛸️

multi threading

ThreadThread 클래스의 여러 메서드들Thread 우선순위join()interrupt()동기화synchronized 메서드synchronized 블럭deadlockwait() / notify() 메서드를 활용한 동기화 프로그래밍
 

Thread

  • Process : 프로그램이 OS로부터 메모리를 할당받아 실행되면 이를 프로세스라고 함
  • thread : process 가 구동이 되려면 cpu를 점유해야 하는데 cpu를 점유하는 단위는 thread
    • 하나의 프로세스는 하나 이상의 thread를 가짐
    • 실제 작업을 수행 하는 단위가 thread
  • context : thread가 자신만의 작업공간을 가짐. 각각의 thread별로 사용하는 변수가 다를테니
  • Shared resource : thread가 동시에 공유하는 자원 (Java에서는 static instance)
    • 이 자원을 여러 thread에서 동시에 접근할때 문제가 생길 수 있음
    • 서로 자원을 차지하려는 race condition이 발생할 수 있음
    • critical section : 여러 thread가 공유하는 자원 중 경쟁이 발생하는 부분 ⇒ 동기화가 필요 (일종의 순차적 수행.하게끔 lock을 거는것)
notion image
  • thread.start를 하면 Runnable의 상태로 들어가게 됨. 실행가능한 상태
    • CPU 배분이 되면 run이 됨

Thread 클래스의 여러 메서드들

Thread 우선순위

  • Thread.MIN_PRIORITY ~ Thread.MAX_PRIORITY

join()

  • 동시에 두개 이상의 Thread가 실행 될 때 다른 Thread의 결과를 참조하여 실행해야 하는 경우 join() 함수를 사용
  • join()함수를 호출한 Thread가 non-runnable 상태가 됨

interrupt()

  • 다른 Thread에 예외를 발생시키는 interrupt를 보낸다
  • Thread가 join(), sleep(), wait() 함수에 의해 not-runnable 상태일 때 interrupt() 메서드를 호출하면 다시 runnable 상태가 될 수 있음

동기화

notion image
  • critical section 은 두 개 이상의 thread가 동시에 접근 하는 경우 문제가 생길 수 있기 때문에 동시에 접근할 수 없는 영역
  • semaphore 는 특별한 형태의 시스템 객체이며 get/release 두 개의 기능이 있다.
  • 한 순간 오직 하나의 thread 만이 semaphore를 얻을 수 있고, 나머지 thread들은 대기(blocking) 상태가 된다.
  • producer consumer문제.. 와 마찬가지로 consume하는 동안 produce가 call 되면 안되는것. 한번에 하나씩

synchronized 메서드

  • synchronized method로 구현되면, 이 method가 수행되는 동안 method가 포함된 객체에 lock을 적용하고 다른 곳에서 이 객체에 접근을 불가능하게 만들어줌

synchronized 블럭

  • synchronized block 방식은 synchronized 하고 괄호안에 어떤 리소스(객체 변수)에 sync를 걸건지를 정해주면 됨

deadlock

notion image
  • Thread1은 끝나려면 L2의 락이 풀려야 하는데 Thread2는 끝나려면 L1의 락이 풀려야 하는 상황. 서로 Lock을 걸고 있어서 끝날수가 없는 상황을 deadlock
  • synchronized 메서드에서 다른 synchronized메서드 호출하지마라!
    • 자바에서는 deadlock에 대한 해결책이 없음. 그래서 호출 중복으로 하지마라

wait() / notify() 메서드를 활용한 동기화 프로그래밍

  • 리소스가 어떤 조건에서 더 이상 유효하지 않은 경우 리소스를 기다리기 위해 Thread가 wait() 상태가 됨
  • wait() 상태가 된 Thread는 notify() 가 호출 될 때까지 기다림
  • 유효한 자원이 생기면 notify()가 호출되고 wait() 하고 있는 Thread 중 무작위로 하나의 Thread를 재시작 하도록 한다.
  • notifyAll() : wait() 하고 있는 모든 Thread가 재시작
    • 이 경우 유효한 리소스만큼의 Thread만이 수행될 수 있고 자원을 갖지 못한 Thread의 경우는 다시 wait() 상태로 만든다.
    • 자바에서는 notifyAll() 메서드의 사용을 권장한다.
// 첫번째 방법 class MyThread extends Thread{ public void run() { int i; for(i=1; i<200;i++) { System.out.print(i + "\t"); } } } // 두번째 방법 class MyThread implements Runnable{ @Override public void run() { int i; for (i=0; i<200; i++) { System.out.print(i + "\t"); } } }
public class JoinTest extends Thread{ int start; int end; int total; public JoinTest(int start, int end){ this.start = start; this.end = end; } public void run(){ int i; for(i = start; i <= end; i++){ total += i; } } public static void main(String[] args) { JoinTest jt1 = new JoinTest(1, 50); JoinTest jt2 = new JoinTest(51, 100); jt1.start(); jt2.start(); try{ jt1.join(); // main Thread에서 jt1에 join을 호출한것. main Thread가 non Runnable하게됨 jt2.join(); }catch (InterruptedException e) { System.out.println(e); } int lastTotal = jt1.total + jt2.total; System.out.println("jt1.total = " + jt1.total); System.out.println("jt2.total = " + jt2.total); System.out.println("lastTotal = " + lastTotal); } }
class Bank{ private int money = 10000; // synchronized method 방식 public synchronized void saveMoney(int save) { //...body... } // synchronized block 방식 public void setMoney(int save){ synchronized (this){ // ...body... }
class Park extends Thread{ public void run() { synchronized (SyncMain.myBank){ System.out.println("start save"); SyncMain.myBank.saveMoney(3000); System.out.println("saveMoney(3000) : " + SyncMain.myBank.getMoney()); } } }