ryanjang-devnotes
Published in

ryanjang-devnotes

자바의 동시적 프로그래밍

이 글은 Javarevisited에 실린 저의 [Java] Concurrent Programming 을 번역하였습니다.

사용자들은 시스템이 동시에 한 가지 이상의 일을 할 수 있다고 확신한다. 그들은 파일을 다운로드하면서, 출력하기 위해 걸어놓은 프린트 큐를 관리하고, 오디오를 틀어 놓으면서 워드로 작업을 계속할 수 있다고 생각한다. 이러한 것들을 가능하게 만드는 것이 바로 동시성 소프트웨어이다.

Oracle

동시성 소프트웨어란 무엇인가?

오라클에서 나온 자바 튜토리얼의 정의보다 동시성 프로그래밍을 잘 정의내린 글은 찾기 힘듭니다. 동시성 프로그래밍은 ‘겹쳐진 시간 동안 돌아가는 여러 개의 동작 시퀀스’ 라고 정의됩니다. 자바에서는 Thread 클래스를 이용해 이러한 동시성을 지원하고 있습니다.

스레드란?

스레드란 어떤 프로그램에서 실행되는 것을 말합니다. JVM은 어플리케이션이 여러개의 스레드로 동시에 돌아갈 수 있도록 하는 것을 허용하고 있습니다. 이러한 멀티-스레드 환경을 더욱 잘 이해하기 위해서는, 각각의 스레드들이 어떻게 상호작용하는 가를 살펴볼 필요가 있습니다.

모든 스레드는 우선순위를 가지고 있습니다. 더 높은 우선순위를 가진 스페드들은 그렇지 않은 것들보다 먼저 실행됩니다. 또, 아마 여러분들은 가끔 ‘daemon’ 이라고 표시된 스레드를 보셨을 지도 모릅니다. Daemon thread란, 가비지 컬렉션과 같이 백그라운드에서 동작하며 작업을 수행하는 낮은 우선순위의 스레드를 말합니다. 새로운 스레드 객체를 생성하는 코드에서 새롭게 만들어지는 스레드는 그것을 만드는 스레드와 초기에 같은 우선순위를 가지게 되는데, 이 때 그 스레드가 daemon 인 경우에 만들어지는 스레드 또한 daemon이 됩니다.

스레드는 어떻게 만들어지는가?

스레드 인스턴스를 만드는 어플리케이션은 그 스레드에서 동작하는 코드를 제공해야만 합니다. 여기에는 두 가지 방식이 있습니다.

첫 번째는 Thread 객체를 상속하는 하위 클래스를 만들고, 부모 클래스의 run() 을 오버라이딩하는 것입니다. 다른 하나는, 스레드의 상속없이 곧바로 Runnable 를 파라미터로 제공할 수도 있습니다. Runnable 인터페이스를 사용할 때에는 전자와 비슷하게 스레드에서 실행될 코드를 담는 run() 단일 메소드를 구현해야 합니다. 예제 코드에서 보듯, 이렇게 인스턴스화된 Runnable 객체는 Thread 생성자에 전달되어, start() 를 통해 실행됩니다.

어떤 것이 더 좋아보이나요? 오라클의 자료에 따르면, Runnable 객체를 사용하는 것이 더 일반 적이라고 합니다. 왜냐하면, 이 경우 Thread 외에 다른 클래스를 상속받을 수 있기 때문이죠.

스레드를 이용한 다양한 동작들

sleep() 을 이용한 실행 중단

Thread.sleep() 은 현재 스레드가 정해진 시간동안 실행되지 않도록 만듭니다. 현재 이 메소드가 실행되고 있을 때 인터럽트에 의해 실행 중단이 되면 해당 스레드는 InterruptException 을 발생시킵니다. 이 예외 클래스는 보통 하나의 스레드가 다른 활동 중인 스레드를 방해할 때 발생합니다.

interrupt() 을 이용한 개입

Thread.interrupt()Thread.sleep() 과는 달리 현재 스레드의 실행을 중지하고, 다른 일을 하게 만듭니다. 이 메소드를 통해 하나의 스레드는 다른 스레드에 인터럽트를 발생시키게 됩니다.

join()을 이용한 다른 스레드에 대한 기다림

join 메소드는 특정 스레드의 작업이 끝날 때까지 다른 메소드가 이를 기다리게 만듭니다. 코드 예제에서와 같이 newThread 가 현재 동작하고 있다면, newThread.join 은 메인 스레드와 합류하게끔 만들고, 이로써 메인 스레드는 newThread 가 중단될 때까지 동작을 잠시 중단하죠.

결론

스레드 객제는 자바 개발자들이 필요한 만큼 많은 오퍼레이션을 관리하게끔 만들어졌습니다. 그래서 얼마나 많은 스레드들을 만들고, 인터럽트에 대응하고, 정해진 시간동안 서로 상호작용하면서 동작하게 만드는 것은 전적으로 개발자들의 선택에 달려있죠. 하지만, 스레드의 갯수가 증가함에 따라 그것들을 관리하는 것은 여간 까다로운 일이 아닙니다. 그로 인해, 이를 좀 더 효율적으로 처리할 수 있는 방법들이 차츰 고안되었는데, 이 이야기는 추후 다뤄보겠습니다. 읽어주셔서 감사합니다.

--

--

Backend engineer, Data Analyst, Political Scientist, Lifelong Learner — github : https://github.com/wkdalsgh192

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Minho Jang

Minho Jang

Backend Developer, Writer, and Lifelong Learner