먼저 쓰레드에 대해 알아보자!
우리는 Java에서 여러가지 일을 동시에 처리하기 위해 Thread를 사용한다.
이때 Thread는 프로세스에 종속되어 있어, 우리는 프로세스를 먼저 알아봐야 한다.
고로 알아보자.
Process
Process는 일반적으로 CPU에 의해 메모리에 올려져 실행중인 프로그램을 말한다.
자신만의 메모리 공간을 포함한 독립적인 실행 환경을 가지고 있으며, JVM은 주로 하나의 프로세스로 실행되며, 동시에 여러 작업을 수행하기 위해 멀티 스레드를 지원하고 있다.
그렇다면 Thread는?
Thread
Thread는 프로세스안에서 실질적으로 작업을 실행하는 단위이다.
자바에서는 JVM에 의해 관리되고, Process에는 적어도 한 개 이상의 Thread가 존재하며 Main Thread 하나로 시작하여 Thread를 추가 생성하게 되면 Multi Thread 환경이 된다. 이러한 Thread들은 프로세스의 리소스를 공유하기 때문에 효율적이지만 잠재적인 문제점에 노출될 수 있다.
자바에서 Thread는 다음과 같은 방법으로 구현할 수 있다.
Runnable 인터페이스 구현 방법부터 알아보자!
Runnable Interface
class ThreadWithRunnable implements Runnable{ public void run(){ System.out.println(Thread.currentThread().getName()); try{ Thread.sleep(10); }catch(InterruptedException e){ e.printStackTrace(); } } }
이제 Thread 클래스를 상속받는 방법에 대해 알아보자!
Thread Class
public class ThreadWithClass extends Thread{ public void run(){ System.out.println(getName()); try{ Thread.sleep(10); }catch(InterruptedException e){ e.printStackTrace(); } } }
위의 방법 모두 다음과 같이 실행시킬 수 있다.
public class Thread0{
ThreadWithClass thread1 = new ThreadWithClass();
Thread thread2 = new Thread(new ThreadWithRunnable());
thread1.start();
thread2.start();
}
자바에서 멀티스레드를 이용하면 여러 작업을 동시에 처리할 수 있기 때문에 작업 효율이 좋아진다.
하지만 하나의 공유 자원을 여러 스레드에서 동시에 접근하여 사용하게 되면 문제가 생길 수 있다.
이러한 문제를 해결하기 위해 우리는 스레드 동기화(Thread Synchronized)를 사용한다.
Synchronized는 멀티스레드 환경에서 여러 Thread가 하나의 공유 자원에 동시에 접근하지 못하도록 막는 것을 의미한다.
공유 데이터가 사용되어 동기화가 필요한 부분을 임계 영역(Critical Section)이라고 부르며, 자바에서는 이 임계 영역에 synchronized 키워드를 사용하여 여러 Thread가 동시에 접근하는 것을 금지하여 동기화 할 수 있다.
synchronized 키워드는 동기화가 필요한 메소드나 코드 블럭 앞에 사용하여 동기화 할 수 있다. synchronized로 지정된 임계 영역은 한 Thread가 이 영역에 접근하여 사용할 때, lock이 걸림으로써 다른 Thread가 접근할 수 없게 한다.
이후 해당 Thread가 이 임계 영역의 코드를 다 실행 후 벗어나게 되면 unlock 상태가 되어 대기하고 있던 다른 Thread가 이 임계 영역에 접근하여 다시 lock을 걸고 사용할 수 있게 된다.
lock은 해당 객체 당 하나씩 존재하며, synchronized로 설정된 임계 영역은 lock권한을 얻은 하나의 객체만이 독점적으로 사용할 수 있다.
한 번 써보자!
//메소드에서 sync 설정하기
synchronized void print(){
System.out.println("dsa");
}
//코드 블럭에서 sync 설정하기
void print(){
synchronized(this){
System.out.println("dsa");
}
}
메소드 앞에 sync 키워드를 사용하면 해당 메소드 전체를 임계 영역으로 설정할 수 있으며,
동기화를 많이 사용하게 되면 효율이 떨어지게 되므로 꼭 필요한 부분에만 블럭을 지정하여 sync를 사용할 수 있다.
끝!
https://kadosholy.tistory.com/121
http://www.tcpschool.com/java/java_thread_concept
https://kadosholy.tistory.com/123