고양이 여름이의 지식채널
JAVA 쓰레드(Thread)와 동시성(Concurrency) 이해하기 본문
쓰레드(Thread)란?
자바에서 쓰레드는 하나의 프로세스 내에서 독립적으로 실행될 수 있는 작은 실행 단위를 의미합니다. 각각의 쓰레드는 자신만의 스택 메모리와 PC(Program Counter) 값을 가지고 실행됩니다.
쓰레드를 실행시키면 해당 쓰레드가 병렬적으로 동작하여, 다음과 같은 동작을 수행할 수 있습니다.
- 쓰레드가 실행하는 코드를 처리합니다.
- 다른 쓰레드와 동시에 실행될 수 있습니다.
- 쓰레드가 가지고 있는 스택 메모리에서 연산을 수행합니다.
- 쓰레드는 다른 쓰레드의 메모리 공간에 직접적으로 접근할 수 없으며, 각 쓰레드는 독립적으로 실행됩니다.
- 쓰레드의 우선순위에 따라 실행 순서가 결정됩니다.
쓰레드를 활용하면 여러 작업을 동시에 처리할 수 있으며, 이를 통해 작업의 효율성을 높일 수 있습니다. 하지만 쓰레드를 잘못 사용하면 동기화 문제 등의 문제가 발생할 수 있으므로 주의가 필요합니다.
쓰레드 생성
쓰레드는 Thread 클래스를 상속받아서 구현하거나 Runnable 인터페이스를 구현하여 생성할 수 있습니다.
- Thread 클래스를 상속받아 구현하는 방법
public class MyThread extends Thread {
public void run() {
// 쓰레드가 실행할 코드
}
}
- Runnable 인터페이스를 구현하는 방법
public class MyRunnable implements Runnable {
public void run() {
// 쓰레드가 실행할 코드
}
}
- 쓰레드 생성 및 실행
public static void main(String[] args) {
// Thread 클래스를 상속받아 구현한 경우
MyThread myThread = new MyThread();
myThread.start();
// Runnable 인터페이스를 구현한 경우
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
}
동시성(Concurrency)이란?
동시성은 여러 개의 쓰레드가 동시에 실행되는 것을 의미합니다. 이를 통해 하나의 프로그램 내에서 여러 가지 작업을 병렬적으로 처리할 수 있습니다. 하지만 이러한 동시성 처리가 잘못 이루어질 경우 데이터 일관성 등의 문제가 발생할 수 있으므로 주의해야 합니다.
쓰레드 동기화(Synchronization)
여러 개의 쓰레드가 공유하는 데이터가 있을 경우, 동시에 해당 데이터를 수정하게 되면 데이터 일관성에 문제가 발생할 수 있습니다. 이를 해결하기 위해 쓰레드 동기화(Synchronization)가 필요합니다. 쓰레드 동기화는 여러 개의 쓰레드가 공유하는 데이터를 안전하게 사용하기 위해 쓰레드 간의 순서를 정해주는 기능입니다.
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized void decrement() {
count--;
}
public synchronized int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
counter.decrement();
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(counter.getCount()); // 0
}
}
위의 코드에서는 Counter 클래스가 count 변수를 공유합니다. increment() 메소드와 decrement() 메소드, getCount() 메소드를 synchronized 키워드로 선언하여 쓰레드 간의 순서를 정합니다. 따라서 여러 개의 쓰레드가 count 변수를 안전하게 사용할 수 있게 됩니다.