자바 병렬 프로그래밍 | 프로세스는 뭐고 스레드는 뭔가요? 상위 246개 답변

당신은 주제를 찾고 있습니까 “자바 병렬 프로그래밍 – 프로세스는 뭐고 스레드는 뭔가요?“? 다음 카테고리의 웹사이트 you.tfvp.org 에서 귀하의 모든 질문에 답변해 드립니다: https://you.tfvp.org/blog/. 바로 아래에서 답을 찾을 수 있습니다. 작성자 얄팍한 코딩사전 이(가) 작성한 기사에는 조회수 77,112회 및 좋아요 2,237개 개의 좋아요가 있습니다.

자바 병렬 프로그래밍 주제에 대한 동영상 보기

여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!

d여기에서 프로세스는 뭐고 스레드는 뭔가요? – 자바 병렬 프로그래밍 주제에 대한 세부정보를 참조하세요

#프로세스 #스레드 #thread
Process와 Thread. 컴공의 운영체제 클래스😪에서 또는
멀티태스킹에 관련한 주제에서 들을 수 있는 용어들이죠.
어려울 수 있지만, 프로그래머로서 반드시 알아야 하는 개념들이에요.
프로세서와 스레드가 무엇이고 서로 어떻게 다른지 살펴보고
자바에서의 스레드 사용도 예제를 통해 알아보기로 하겠습니다.
= = =
🏠 얄코사이트: https://www.yalco.kr
🛒 개발자스티커 구매: https://smartstore.naver.com/honeykers
🎥 가장 쉬운 Git 튜토리얼: https://youtu.be/FXDjmsiv8fI
🎥 포인터 쉽게 알아보기: https://youtu.be/u65F4ECaKaY
🎥 객체지향에 대해 알아보기: https://youtu.be/vrhIxBWSJ04
🎥 객체지향 디자인 패턴: https://youtu.be/lJES5TQTTWE
🎥 함수형 프로그래밍이란?: https://youtu.be/jVG5jvOzu9Y
🎥 쿠키 vs 세션 vs 캐시: https://youtu.be/OpoVuwxGRDI
🎥 프로세스와 스레드: https://youtu.be/iks_Xb9DtTM
🎥 비동기 프로그래밍: https://youtu.be/m0icCqHY39U
🎥 REST API 알아보기: https://youtu.be/iOueE9AXDQQ
🎥 GraphQL 알아보기: https://youtu.be/EkWI6Ru8lFQ
= = =
🎬 영상 주요 포인트
⚙️ 프로세스의 개념
여러분의 컴퓨터에서 실행할 수 있는 파일
윈도우의 경우 이름 뒤쪽에 .exe 붙어있는
그런 파일들을 ‘프로그램’이라고 해요.
그리고 그 프로그램이 실행돼서
돌아가가고 있는 상태,
즉 컴퓨터가 어떤 일을 하고 있는 상태를
‘프로세스’라고 하죠.

여러 프로세스를 함께 돌리는 작업은
동시적, 병렬적, 또는
이 둘의 혼합으로 이뤄져요.

동시성은 프로세서 하나가
이거 조금 하고 이거 조금 하고 이거 조금 하고
이렇게 여러 작업을 돌아가면서
일부분씩 진행하는거에요.

이 과정이 Git똥차게 빨리 돌아가니까
사람에게는 이 프로세스들이
동시에 진행되는 것처럼 느껴지는거죠.
병렬성은 프로세서 하나에
코어 여러 개가 달려서
각각 동시에 작업들을 수행하는거에요.
듀얼코어 쿼드코어 옥타코어
이런 명칭이 붙는 멀티코어 프로세서가 달린
컴퓨터에서 할 수 있는 방식이죠.
CPU의 속도가 발열 등 물리적 제약 때문에
예전만큼 빠르게 발전하지 못하자
그 대안으로, 코어를 여러 개 달아서
작업을 분담할 수 있도록 만든거에요.
🧵 스레드의 개념
한 프로세스 내에서도 여러 갈래의 작업들이
동시에 진행될 필요가 있는거에요.
이 갈래를 ‘스레드’라고 불러요.
이 영상에서 메모리를 조리대에 비유했죠?
프로세서는 요리사고,
대량주문이 들어오는 이 식당에서
끊임없이 만들어내는 요리 메뉴
하나하나가 프로세스에요.
컴퓨터는 프로세스마다 자원을 분할해서 할당해요.
라면 끓이는 섹션, 김밥 마는 섹션, 햄버거 만드는 섹션
이렇게 조리 공간을 나눠서
요리사 혼자서 돌아다니면서 동시적으로 하든
여럿이서 병렬적으로 하든, 이들을 섞어서 하든
이 메뉴들을 계속해서 만들어내는거죠.
햄버거를 만드는 프로세스에서는
패티를 굽는 스레드가 진행되는 동안
빵에 야채를 얹고 소스를 뿌리는
스레드도 진행될 수 있겠죠.
한 메뉴의 스레드들은 같은 조리대에서 이뤄져요.
패티는 여기서 굽고 야채는 여기서 얹는다면
같은 조리대에서 작업하는 것보다
일하기가 더 힘들겠죠.
같은 메뉴를 만들 때는 같은 공간과 장비,
즉 같은 자원을 공유하는것이
더 효율적일거에요.
프로세스들은 컴퓨터의 자원을 분할해서 쓰지만
스레드는 프로세스마다 주어진 전체 자원을
함께 사용하는거죠.
이게 속도와 효율 면에서는 낫겠지만
단점도 있어요.
프로세스 안에서 공유되는 변수에
스레드 두 개가 동시에 손을 대요.
현실세계에서는 로맨스물이 되지만
컴퓨터 세계에서는 Error물이 돼요.
= = =
🎵 엔딩송 : 권민호, 김한영 – Let’s Dance
🎼 자료출처 : https://gongu.copyright.or.kr
🎼 Music promoted by DayDreamSound : https://youtu.be/L16GOic2UXw

자바 병렬 프로그래밍 주제에 대한 자세한 내용은 여기를 참조하세요.

자바 병렬 프로그래밍 – YES24

스레드는 자바 플랫폼에서 가장 기본적으로 제공되는 기능 중 하나다. 멀티코어 프로세서가 대중화되면서 고성능 애플리케이션을 작성할 때 병렬 처리 능력을 …

+ 더 읽기

Source: www.yes24.com

Date Published: 5/29/2022

View: 5957

(멀티코어를 100% 활용하는) 자바 병렬 프로그래밍 – 교보문고

이 책은 자바 병렬 프로그래밍 참고 매뉴얼이다. 병렬 처리 관련 기능에 어떤 것이 있고, 어떻게 사용하는지에 대한 방법뿐 아니라, 그 내부에 숨어 있는 디자인 패턴 …

+ 여기에 더 보기

Source: www.kyobobook.co.kr

Date Published: 6/17/2021

View: 1368

자바 병렬 프로그래밍 volatile과 synchronized – Loner의 학습노트

[자바 병렬 프로그래밍]. – 병렬 프로그래밍이라는 것은, 개발자가 소스코드를 작성할 때, 위에서 아래로 차례대로 흐르는 방식의 코드 흐름을 작성 …

+ 여기에 자세히 보기

Source: wiserloner.tistory.com

Date Published: 6/29/2022

View: 6763

자바 병렬 프로그래밍 – 알라딘

자바 병렬 프로그래밍 멀티코어를 100% 활용하는. 조슈아 블로크, 브라이언 게츠, 팀 피얼스, 조셉 보우비어, 더그 리, 데이빗 홈즈 (지은이), 강철구 (옮긴이) 에이콘 …

+ 여기에 보기

Source: www.aladin.co.kr

Date Published: 3/29/2021

View: 5447

멀티 스레드 병렬 프로그래밍을 하기 전 반드시 읽어야할 것들

java.util.concurrent 패키지 내용을 정리하려고 하다가 기본 지식이 부족하다 생각하여 JAVA 병렬 프로그래밍이라는 책을 읽고 멀티 스레드 …

+ 더 읽기

Source: jeong-pro.tistory.com

Date Published: 1/2/2021

View: 9548

멀티코어를 100% 활용하는 자바 병렬 프로그래밍 – 11번가

멀티코어를 100% 활용하는 자바 병렬 프로그래밍. 현재 판매중인 상품이 아닙니다. 배송. 무료배송 (20,000원 이상 무료). 배송 안내. – 최근 3개월의 배송데이터 기반 …

+ 자세한 내용은 여기를 클릭하십시오

Source: m.11st.co.kr

Date Published: 2/9/2021

View: 7232

주제와 관련된 이미지 자바 병렬 프로그래밍

주제와 관련된 더 많은 사진을 참조하십시오 프로세스는 뭐고 스레드는 뭔가요?. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.

프로세스는 뭐고 스레드는 뭔가요?
프로세스는 뭐고 스레드는 뭔가요?

주제에 대한 기사 평가 자바 병렬 프로그래밍

  • Author: 얄팍한 코딩사전
  • Views: 조회수 77,112회
  • Likes: 좋아요 2,237개
  • Date Published: 2019. 5. 21.
  • Video Url link: https://www.youtube.com/watch?v=iks_Xb9DtTM

자바 병렬 프로그래밍

이 책을 쓰는 시점에도 일반적인 데스크탑 시스템에서조차 멀티코어 프로세서가 비싸지 않은 가격으로 대중화되어 가고 있다. 우연찮게 수많은 개발팀이 진행하는 프로젝트에서 스레드와 관련된 버그가 자꾸만 늘어나고 있다는 사실을 쉽게 알 수 있다. 넷빈즈(NetBeans) 개발 사이트에 최근에 올라온 글을 보면, 단 하나의 클래스를 놓고 스레드 관련 문제점을 수정하기 위해 14번이나 코드를 수정했다는 사실을 핵심 유지보수 담당자가 알아차린 사례도 있다. TheServerSide의 편집장을 지냈던 디온 앨메어는 (결국 스레드 관련 문제라고 결론이 나왔던 고통스러운 디버깅 작업을 끝낸 이후에) 대부분의 자바 프로그램이 “어쩌다보니 실수로 동작하는” 것일 뿐이며 스레드 관련 버그가 굉장히 자주 발생한다는 내용의 블로그 포스트를 올린 적도 있다.

스레드 관련 오류는 예측 가능한 상태로 스스로를 드러내는 법이 거의 없기 때문에 스레드를 사용하는 프로그램을 개발하고 테스트하고 디버그하는 일은 실제로 엄청나게 어려운 일이 될 수 있다. 게다가 문제점은 항상 최악의 시점, 즉 실제 사용 환경에서 부하가 많이 걸릴 때 주로 나타난다.

자바로 병렬 프로그램을 작성할 때 넘어야 할 가장 큰 산중의 하나는 플랫폼에서 제공하는 병렬 프로그래밍 기법과 개발자가 자신의 프로그램에서 병렬 프로그래밍 기법을 어떻게 사용하려 하는지 간에 큰 차이가 있다는 점이다. 자바 언어에서는 동기화나 조건부 대기와 같은 저수준의 도구(mechanism)를 제공하지만, 이런 도구를 사용해 애플리케이션 수준의 규칙이나 정책(policy)을 일관적으로 구현할 수 있어야 한다. 컴파일 잘 되고 실행도 잘 된다고 생각되는 프로그램은 쉽게 작성할 수 있겠지만, 이런 정책이 없다면 오류가 금새 나타나고야 만다. 병렬 프로그래밍에 대한 다른 훌륭한 책이 많지만 대부분 설계 수준의 정책이나 패턴에 대해서 다루기 보다는 저수준의 API에 집중하고 있어 이와 같은 정책의 중요성에 대처하는 면이 부족했다고 생각된다.

자바5.0은 고수준의 컴포넌트와 저수준의 도구를 모두 제공하기 때문에 초보자나 전문가 모두가 병렬 프로그램을 쉽게 작성할 수 있게 되었다는 점에서 큰 발전을 이뤘다고 볼 수 있다. 이런 기능을 실제로 구현하는데 참여했던 JCP 전문가 그룹에서 이 책을 쓰는데 많이 참여했다. 추가된 기능과 동작하는 구조를 설명하는 것뿐만 아니라 그 기반이 되는 디자인 패턴과 함께 플랫폼 라이브러리에 추가되는데 중요한 역할을 했던 예상 활용 시나리오도 함께 소개한다.

이 책을 읽는 독자는 여러 가지 설계상의 규칙을 이해하고, 또한 자바 클래스나 애플리케이션이 올바르게 높은 성능으로 동작하도록 작성하는 과정이 더 쉽고 재미있는 일이 되도록 만들고자 하는 목표가 있다.

『자바 병렬 프로그래밍』을 즐겁게 읽고 유익하게 활용하길 바란다.

— 저자 서문, 브라이언 괴츠(Brian Goetz)

학교를 졸업하고 처음 회사에 취직한 이후에 담당했던 개발 업무 가운데 상당 부분은 자바로 서버 프로그램을 작성하는 일이었습니다. 수십에서 수백 대에 이르는 클라이언트를 대상으로 24시간 동작하는 서버를 작성하는 업무는 꽤나 재미있었습니다. 몇 날 며칠을 고생해서 만든 서버 프로그램이 어딘가 누군가의 서버에 설치되어 24시간 동작하면서 제 할 일을 하고 있는 모습을 보면 건방지게도 자식이 제 할 일을 잘 할 때 부모가 받았을 느낌을 느낄 수 있었다고도 생각합니다.

하지만 어려운 병렬 처리 이론이 아닌 멀티스레드를 사용해 프로그램하는 실습 위주의 교육을 받은 적이 없는지라, 단순하게 멀티스레드로만 동작하는 ‘자식같은’ 프로그램이 알 수 없는 오류를 뿌리면서 곳곳에서 뻗어버리는 모습을 보면 참 안타까웠습니다 (오류라도 뿌리고 죽으면 그나마 다행입니다). 예전 버전의 자바는 운영체제마다 스레드의 동작 모습이 많이 달라서 어려운 점도 많았습니다. 운영체제마다 다른 스케줄링 문제를 해결하기 위해 전반적인 성능을 떨어뜨리면서 쓸모없는 I/O 구문을 추가하는 작업도 서슴치 않았습니다. 이후 스레드 풀을 적용해 서버의 안정성을 크게 높여주고, 스핀락(spin-lock)을 사용했던 부분에 wait-notify 구조를 적용해 CPU 부하를 크게 줄이기도 했습니다. 그러던 도중에 자바5.0이 발표되고, 병렬 프로그래밍을 위한 도구가 엄청나게 많이 제공되기 시작했습니다. 여기저기 찾아보며 만들고 안정화하느라 애를 먹었던 스레드 풀을 메소드 호출 한방으로 만들 수 있었으며, 훨씬 다양한 병렬 프로그래밍 기능을 더 안정적으로 제공받을 수 있게 되었죠.

이제 어느 프로그램에나 멀티스레드 구조를 활용하는 일은 거의 기본이 되어갑니다. 제가 요즘 맡은 개발 업무에서도 완전히 서로 다른 분야의 동떨어진 목표를 향해 개발하지만, 어느 곳 하나 스레드를 활용하지 않는 프로젝트가 없습니다. 서버에서는 한정된 컴퓨터 자원을 최대한 활용해 가장 효율적으로 서비스를 제공하고자 하고, 클라이언트 PC에서는 동적인 인터페이스와 함께 많은 정보를 실시간으로 얻고자 하죠. 단순히 언어와 관련된 문제는 아닙니다. 자바이건 C#이건 PHP이건 간에 항상 멀티스레드 환경을 생각해야 합니다. 직접 스레드를 만들지 않더라도 외부의 어디선가 반드시 스레드를 사용하는 부분이 있게 마련입니다.

이런 시점에 스레드를 활용한 병렬 처리에 대한 실제적인 예제와 패턴을 적용한 사용 예를 소개하는 너무나 반가운 책이 바로 『(멀티코어를 100% 활용하는) 자바 병렬 프로그래밍』입니다.

병렬 프로그램을 작성할 때 보통은 자바5.0부터 추가된 java.util.concurrent 패키지에 대한 여러 문서를 보면서 대충 이해하고 사용하곤 하지만, 『자바 병렬 프로그래밍』은 이런 기능을 충분히 이해한 상태에서 활용하도록 도와주고 있습니다. 아주 간단한 클래스를 담당해 개발하고 있다고 해도, 해당 클래스가 큰 규모의 프로그램에서 기본적인 부분으로 널리 사용된다면 이 책에서 소개하는 기법을 적절히 적용해 전체 프로그램의 안전성을 확보하면서 성능을 크게 높일 수 있습니다. 그리고 병렬 프로그래밍에 대한 기초를 다지고 나면, 기존에 잊을만 하면 한 번씩 오류를 뱉어내면서 문제가 생기던 프로그램에 어떤 원인이 있을 수 있는지 쉽게 추적할 수도 있습니다. 『자바 병렬 프로그래밍』이 전문적인 이론서는 아니지만, 이론을 소홀하게 다루지도 않습니다. 또한 자바 언어를 기반으로 한다는 가정하에 쓰여진 책입니다만, 일반적인 병렬 처리 이론을 적용한 부분이 많으며 하드웨어나 시스템 구조와 관련된 부분도 적지 않기 때문에 다른 언어에도 쉽게 적용할 수 있는 내용이 많습니다.

한발 더 나아가 미래를 내다보는 개발자는 이미 단일 컴퓨터 내부에서의 병렬 처리를 넘어 여러 대의 컴퓨터에서 병렬로 동작하는 플랫폼을 찾고 있고, 이와 같은 분산 병렬 처리 플랫폼이 한창 인기를 얻는 요즘입니다. 이런 대규모의 병렬 처리 플랫폼도 중요하긴 하지만, 그 안에서는 항상 단일 프로세스 내부에서 동작하는 여러 스레드가 안정적으로 실행되도록 하는 병렬 처리 기법이 적용되어 있음을 잊어서는 안될 것입니다.

재미있겠다고 생각은 했지만 내용이 어렵겠다고 지레 겁을 먹고 사양했던 번역 작업인데, 결국 이제야 끝마치게 되었습니다. 나름 서버 프로그래밍을 통해 경험을 많이 쌓았다고 생각했지만 책을 꼼꼼히 읽는 과정에서 배운 점이 더 많았습니다. 여러분 모두 이 책을 통해 자신있게 스레드를 널리 활용하고 결과물의 성능과 안전성을 높일 수 있게 되길 바랍니다.

참고로, 이 책에서 ‘병렬’이라는 단어로 표시한 내용의 대부분은 ‘concurrent’라는 영어 단어를 의미합니다. concurrent의 뜻은 특히 컴퓨터 용어로 쓰일 때 ‘동시에 실행되는 코드의 흐름’이라고 풀어 쓸 수 있겠습니다. 원래 ‘병렬’은 일반적으로 ‘parallel’이라는 단어를 번역할 때 많이 사용합니다. 하지만 parallel과 concurrent는 약간의 뉘앙스 차이가 있음에도 불구하고 비슷한 의미로 볼 수 있기 때문에 ‘병렬’이라는 단어를 사용했다는 점을 알립니다.

마지막으로 이 책을 번역할 수 있게 물심 양면으로 도움을 아끼지 않았던 아내 선영과 아들 강헌에게 고맙다는 인사를 전합니다. 가족은 항상 저를 든든하게 만드는 능력이 있습니다.

— 역자 서문

자바 병렬 프로그래밍(멀티코어를 100% 활용하는)(원서/번역서: [해외]Java Concurrency in Practice (Paperback))

스레드는 자바 플랫폼에서 가장 기본적으로 제공되는 기능 중 하나다. 멀티코어 프로세서가 대중화되면서 고성능 애플리케이션을 작성할 때 병렬 처리 능력을 효과적으로 활용하는 일의 중요성이 점차 부각되고 있다. 자바 SE 5와 6은 JVM 수준에서 뛰어난 성능과 높은 확장성을 함께 확보할 수 있도록 지원하고 다양한 종류의 병렬 처리 기반을 라이브러리로 제공하고 있어 병렬 처리 애플리케이션을 작성하고자 할 때 큰 짐을 덜어준다. 이같은 기능을 자바에 추가한 핵심 인력이 직접 집필한 이 책에서는, 병렬 처리 관련 기능에 어떤 것이 있고 어떻게 사용하는지에 대한 방법뿐 아니라, 그 내부에 숨어 있는 디자인 패턴과 그 패턴을 사용한 원론적인 이유도 함께 소개한다.멀티스레드 프로그램을 작성하고 테스트하고 디버깅하는 일은 여전히 굉장히 어려운 작업이다. 병렬 처리 프로그램이 올바르게 동작하는 것처럼 보일 정도로 만들기는 쉽지만, 실서버에 적용하고 부하가 걸리는 시점이 되면 어김없이 오류가 발생한다. 이 책을 읽은 독자는 이론적인 기반과 함께 안정적이고 확장성 높고 유지보수가 간편한 병렬 처리 프로그램을 작성하는 방법을 배울 수 있다. 이 책에서 병렬 처리 API와 그 구조에 어떤 것이 있는지 뿐만 아니라 설계상의 규칙, 디자인 패턴, 그리고 병렬 처리 프로그램을 작성하는 개발자가 갖춰야 할 자세까지 익힘으로써, 올바르게 동작하면서 동시에 훌륭한 성능을 지닌 병렬 처리 프로그램을 작성할 수 있다.자바5.0과 자바6 버전에서 자바 플랫폼에 추가된 병렬 프로그래밍 기법을 설계하고 구현하는 멋진 팀에서 일할 수 있어서 너무나 행운이라고 생각합니다. 이제 그 멋진 팀에서 병렬 프로그램을 위한 새로운 기능뿐만 아니라 전반적인 병렬 프로그래밍 관련 내용까지 설명하고 있습니다. 병렬 프로그램은 더 이상 고급 개발자만이 할 수 있는 일이 아닙니다. 자바 개발자라면 반드시 읽어봐야 할 책입니다.- 마틴 부시홀즈(Martin Buchholz) 썬마이크로시스템즈 JDK 병렬 프로그래밍 전문가지난 30년간 컴퓨터 프로그램의 성능은 무어의 법칙(Moore’s Law)에 따라 성장해왔습니다. 하지만 이제부터는 암달의 법칙(Amdahl’s Law)에 의해 발전하게 될 것입니다. 여러 개의 프로세서를 효율적으로 활용하는 프로그램을 작성한다는 건 굉장히 어려운 일입니다. 『자바 병렬 프로그래밍』은 최신 하드웨어 또는 앞으로 사용하게 될 미래의 시스템에서 안전하면서 확장성 높게 동작할 수 있는 자바 프로그램을 작성하는 데 꼭 필요한 개념과 기법을 소개합니다.- 도런 레이원(Doron Rajwan) 인텔 연구 과학자멀티스레드로 동작하는 자바 프로그램을 개발하거나 설계하거나 디버깅하고 있거나 유지보수하고 있거나 그냥 자세히 뜯어보고 있기라도 하다면 반드시 읽어야 할 책입니다. 메소드에 synchronized 키워드를 적어 넣으면서 왜 그래야만 하는지를 충분히 이해하지 못하고 있었다면 본인뿐 아니라 메소드를 사용하는 사용자도 함께 이 책을 처음부터 끝까지 읽어야 합니다.- 테드 뉴워드(Ted Neward) Effective Enterprise Java의 저자저자인 브라이언은 병렬 프로그램과 관련된 원론적인 부분과 그 복잡성을 독보적인 명료함으로 담아내고 있다. 스레드를 사용하거나 성능에 신경을 써야 하는 모든 개발자가 반드시 읽어야 할 책이다.- 커크 페퍼다인(Kirk Pepperdine) JavaPerformanceTuning.com의 CTO이 책에서는 매우 심도있고 세밀한 내용까지 깔끔하고 명료하게 다루고 있으며, 자바 병렬 프로그래밍에 대한 완벽한 참고 매뉴얼이라고 할 수 있다. 개발자 입장에서 일상적으로 다뤄야 하는 다양한 문제점(뿐만 아니라 그 해결책까지)을 자세히 담았다. 무어의 법칙을 통해 더 빠른 프로세서를 만드는 대신 더 많은 프로세서를 사용하는 게 일반화되어 가고 있기 때문에 병렬 프로그램을 효과적으로 작성하는 방법이 점점 더 중요해지고 있으며, 이 책에서 바로 그런 방법을 소개하고 있다.- 클리프 클릭 박사(Dr. Cliff Click) Azul Systems의 선임 소프트웨어 엔지니어개인적으로 병렬 프로그래밍에 관심이 매우 높으며, 어떤 개발자보다도 더 많은 스레드 데드락을 경험해봤으며 동기화 기법을 잘못 사용해본 경험 역시 훨씬 많을지도 모릅니다. 『자바 병렬 프로그래밍』은 자바에서의 스레드와 병렬 프로그래밍에 대해 가장 읽을 만한 책이며, 어려운 주제를 놀랍도록 쉬운 예제로 풀어나가고 있습니다. 이 책은 재미있으면서 굉장히 유용하고 또한 자바 개발자라면 자주 맞닥뜨리는 문제를 직접 다루고 있기 때문에 The Java Specialists’ Newsletter의 독자 모두에게 추천하고 싶은 책입니다.- 하인즈 캐뷰츠 박사(Dr. Heinz Kabutz) The Java Specialists’ Newsletter지금까지 단순한 문제를 단순화하는 일을 해왔지만, 이 책은 복잡하면서도 아주 중요한 주제인 병렬 프로그래밍에 대한 내용을 야심차게 게다가 효과적으로 간결하게 다루고 있습니다. 『자바 병렬 프로그래밍』의 접근 방법은 굉장히 혁신적이며 이해하기 쉽게 쓰여졌고, 적절한 시점에 필요한 내용을 담았습니다. 반드시 굉장히 중요한 책이 되리라고 생각합니다.- 브루스 테이트(Bruce Tate) Beyond Java의 저자『자바 병렬 프로그래밍』은 자바 개발자에게 꼭 필요한 스레드 관련 노하우를 집대성한 위대한 책입니다. 자바 병렬 프로그래밍 API에 대한 훌륭한 가이드이기도 하지만, 어디에서도 찾아볼 수 없을 스레드 관련 전문 지식을 하나도 빼놓지 않으면서도 쉽게 접근할 수 있도록 다루고 있기 때문에 이 책을 읽다 보니 지적인 흥분을 느낍니다.- 빌 베너스(Bill Venners) Inside the Java Virtual Machine의 저자이 책을 쓰는 시점에도 일반적인 데스크탑 시스템에서조차 멀티코어 프로세서가 비싸지 않은 가격으로 대중화되어 가고 있다. 우연찮게 수많은 개발팀이 진행하는 프로젝트에서 스레드와 관련된 버그가 자꾸만 늘어나고 있다는 사실을 쉽게 알 수 있다. 넷빈즈(NetBeans) 개발 사이트에 최근에 올라온 글을 보면, 단 하나의 클래스를 놓고 스레드 관련 문제점을 수정하기 위해 14번이나 코드를 수정했다는 사실을 핵심 유지보수 담당자가 알아차린 사례도 있다. TheServerSide의 편집장을 지냈던 디온 앨메어는 (결국 스레드 관련 문제라고 결론이 나왔던 고통스러운 디버깅 작업을 끝낸 이후에) 대부분의 자바 프로그램이 “어쩌다보니 실수로 동작하는” 것일 뿐이며 스레드 관련 버그가 굉장히 자주 발생한다는 내용의 블로그 포스트를 올린 적도 있다.스레드 관련 오류는 예측 가능한 상태로 스스로를 드러내는 법이 거의 없기 때문에 스레드를 사용하는 프로그램을 개발하고 테스트하고 디버그하는 일은 실제로 엄청나게 어려운 일이 될 수 있다. 게다가 문제점은 항상 최악의 시점, 즉 실제 사용 환경에서 부하가 많이 걸릴 때 주로 나타난다.자바로 병렬 프로그램을 작성할 때 넘어야 할 가장 큰 산중의 하나는 플랫폼에서 제공하는 병렬 프로그래밍 기법과 개발자가 자신의 프로그램에서 병렬 프로그래밍 기법을 어떻게 사용하려 하는지 간에 큰 차이가 있다는 점이다. 자바 언어에서는 동기화나 조건부 대기와 같은 저수준의 도구(mechanism)를 제공하지만, 이런 도구를 사용해 애플리케이션 수준의 규칙이나 정책(policy)을 일관적으로 구현할 수 있어야 한다. 컴파일 잘 되고 실행도 잘 된다고 생각되는 프로그램은 쉽게 작성할 수 있겠지만, 이런 정책이 없다면 오류가 금새 나타나고야 만다. 병렬 프로그래밍에 대한 다른 훌륭한 책이 많지만 대부분 설계 수준의 정책이나 패턴에 대해서 다루기 보다는 저수준의 API에 집중하고 있어 이와 같은 정책의 중요성에 대처하는 면이 부족했다고 생각된다.자바5.0은 고수준의 컴포넌트와 저수준의 도구를 모두 제공하기 때문에 초보자나 전문가 모두가 병렬 프로그램을 쉽게 작성할 수 있게 되었다는 점에서 큰 발전을 이뤘다고 볼 수 있다. 이런 기능을 실제로 구현하는데 참여했던 JCP 전문가 그룹에서 이 책을 쓰는데 많이 참여했다. 추가된 기능과 동작하는 구조를 설명하는 것뿐만 아니라 그 기반이 되는 디자인 패턴과 함께 플랫폼 라이브러리에 추가되는데 중요한 역할을 했던 예상 활용 시나리오도 함께 소개한다.이 책을 읽는 독자는 여러 가지 설계상의 규칙을 이해하고, 또한 자바 클래스나 애플리케이션이 올바르게 높은 성능으로 동작하도록 작성하는 과정이 더 쉽고 재미있는 일이 되도록 만들고자 하는 목표가 있다.『자바 병렬 프로그래밍』을 즐겁게 읽고 유익하게 활용하길 바란다.브라이언 괴츠(Brian Goetz)학교를 졸업하고 처음 회사에 취직한 이후에 담당했던 개발 업무 가운데 상당 부분은 자바로 서버 프로그램을 작성하는 일이었습니다. 수십에서 수백 대에 이르는 클라이언트를 대상으로 24시간 동작하는 서버를 작성하는 업무는 꽤나 재미있었습니다. 몇 날 며칠을 고생해서 만든 서버 프로그램이 어딘가 누군가의 서버에 설치되어 24시간 동작하면서 제 할 일을 하고 있는 모습을 보면 건방지게도 자식이 제 할 일을 잘 할 때 부모가 받았을 느낌을 느낄 수 있었다고도 생각합니다.하지만 어려운 병렬 처리 이론이 아닌 멀티스레드를 사용해 프로그램하는 실습 위주의 교육을 받은 적이 없는지라, 단순하게 멀티스레드로만 동작하는 ‘자식같은’ 프로그램이 알 수 없는 오류를 뿌리면서 곳곳에서 뻗어버리는 모습을 보면 참 안타까웠습니다 (오류라도 뿌리고 죽으면 그나마 다행입니다). 예전 버전의 자바는 운영체제마다 스레드의 동작 모습이 많이 달라서 어려운 점도 많았습니다. 운영체제마다 다른 스케줄링 문제를 해결하기 위해 전반적인 성능을 떨어뜨리면서 쓸모없는 I/O 구문을 추가하는 작업도 서슴치 않았습니다. 이후 스레드 풀을 적용해 서버의 안정성을 크게 높여주고, 스핀락(spin-lock)을 사용했던 부분에 wait-notify 구조를 적용해 CPU 부하를 크게 줄이기도 했습니다. 그러던 도중에 자바5.0이 발표되고, 병렬 프로그래밍을 위한 도구가 엄청나게 많이 제공되기 시작했습니다. 여기저기 찾아보며 만들고 안정화하느라 애를 먹었던 스레드 풀을 메소드 호출 한방으로 만들 수 있었으며, 훨씬 다양한 병렬 프로그래밍 기능을 더 안정적으로 제공받을 수 있게 되었죠.이제 어느 프로그램에나 멀티스레드 구조를 활용하는 일은 거의 기본이 되어갑니다. 제가 요즘 맡은 개발 업무에서도 완전히 서로 다른 분야의 동떨어진 목표를 향해 개발하지만, 어느 곳 하나 스레드를 활용하지 않는 프로젝트가 없습니다. 서버에서는 한정된 컴퓨터 자원을 최대한 활용해 가장 효율적으로 서비스를 제공하고자 하고, 클라이언트 PC에서는 동적인 인터페이스와 함께 많은 정보를 실시간으로 얻고자 하죠. 단순히 언어와 관련된 문제는 아닙니다. 자바이건 C#이건 PHP이건 간에 항상 멀티스레드 환경을 생각해야 합니다. 직접 스레드를 만들지 않더라도 외부의 어디선가 반드시 스레드를 사용하는 부분이 있게 마련입니다.이런 시점에 스레드를 활용한 병렬 처리에 대한 실제적인 예제와 패턴을 적용한 사용 예를 소개하는 너무나 반가운 책이 바로 『(멀티코어를 100% 활용하는) 자바 병렬 프로그래밍』입니다.병렬 프로그램을 작성할 때 보통은 자바5.0부터 추가된 java.util.concurrent 패키지에 대한 여러 문서를 보면서 대충 이해하고 사용하곤 하지만, 『자바 병렬 프로그래밍』은 이런 기능을 충분히 이해한 상태에서 활용하도록 도와주고 있습니다. 아주 간단한 클래스를 담당해 개발하고 있다고 해도, 해당 클래스가 큰 규모의 프로그램에서 기본적인 부분으로 널리 사용된다면 이 책에서 소개하는 기법을 적절히 적용해 전체 프로그램의 안전성을 확보하면서 성능을 크게 높일 수 있습니다. 그리고 병렬 프로그래밍에 대한 기초를 다지고 나면, 기존에 잊을만 하면 한 번씩 오류를 뱉어내면서 문제가 생기던 프로그램에 어떤 원인이 있을 수 있는지 쉽게 추적할 수도 있습니다. 『자바 병렬 프로그래밍』이 전문적인 이론서는 아니지만, 이론을 소홀하게 다루지도 않습니다. 또한 자바 언어를 기반으로 한다는 가정하에 쓰여진 책입니다만, 일반적인 병렬 처리 이론을 적용한 부분이 많으며 하드웨어나 시스템 구조와 관련된 부분도 적지 않기 때문에 다른 언어에도 쉽게 적용할 수 있는 내용이 많습니다.한발 더 나아가 미래를 내다보는 개발자는 이미 단일 컴퓨터 내부에서의 병렬 처리를 넘어 여러 대의 컴퓨터에서 병렬로 동작하는 플랫폼을 찾고 있고, 이와 같은 분산 병렬 처리 플랫폼이 한창 인기를 얻는 요즘입니다. 이런 대규모의 병렬 처리 플랫폼도 중요하긴 하지만, 그 안에서는 항상 단일 프로세스 내부에서 동작하는 여러 스레드가 안정적으로 실행되도록 하는 병렬 처리 기법이 적용되어 있음을 잊어서는 안될 것입니다.재미있겠다고 생각은 했지만 내용이 어렵겠다고 지레 겁을 먹고 사양했던 번역 작업인데, 결국 이제야 끝마치게 되었습니다. 나름 서버 프로그래밍을 통해 경험을 많이 쌓았다고 생각했지만 책을 꼼꼼히 읽는 과정에서 배운 점이 더 많았습니다. 여러분 모두 이 책을 통해 자신있게 스레드를 널리 활용하고 결과물의 성능과 안전성을 높일 수 있게 되길 바랍니다.참고로, 이 책에서 ‘병렬’이라는 단어로 표시한 내용의 대부분은 ‘concurrent’라는 영어 단어를 의미합니다. concurrent의 뜻은 특히 컴퓨터 용어로 쓰일 때 ‘동시에 실행되는 코드의 흐름’이라고 풀어 쓸 수 있겠습니다. 원래 ‘병렬’은 일반적으로 ‘parallel’이라는 단어를 번역할 때 많이 사용합니다. 하지만 parallel과 concurrent는 약간의 뉘앙스 차이가 있음에도 불구하고 비슷한 의미로 볼 수 있기 때문에 ‘병렬’이라는 단어를 사용했다는 점을 알립니다.마지막으로 이 책을 번역할 수 있게 물심 양면으로 도움을 아끼지 않았던 아내 선영과 아들 강헌에게 고맙다는 인사를 전합니다. 가족은 항상 저를 든든하게 만드는 능력이 있습니다. 닫기

Loner의 학습노트 :: 자바 병렬 프로그래밍 volatile과 synchronized

[자바 병렬 프로그래밍]

– 병렬 프로그래밍이라는 것은, 개발자가 소스코드를 작성할 때, 위에서 아래로 차례대로 흐르는 방식의 코드 흐름을 작성하는 것만이 아닌,(일반적으로 hello world를 찍을 때도 사용되는 것이 바로 이 일직선의 코드 흐름입니다.) 한 코드 내에, ‘동시적’으로 실행되는 코드와 로직의 흐름을 만들어 내는 것입니다.

– 요약하자면, 한 프로그램에서 여러 쓰레드를 만들어 동작 시키는 기술입니다.

– 여기선 자바를 중점으로 한 병렬 프로그램에 대해 정리할 것입니다. 어렵지 않으니 차근차근 알아보죠.

(쓰레드)

– 프로세스라는 말을 아십니까?

한 OS에서 동시에 실행되는 프로그램을 프로세스라는 단위로 부릅니다.

멀티 프로세싱이라는 것은, OS가 작동 시키는 프로세스의 갯수가 복수개라는 뜻이죠.

(만일 윈도우 같은 OS를 사용할 때, 한번에 하나의 작업만 가능하다 해봅시다. 그림판이라도 하나 띄워놓는다면 인터넷을 못하고, 인터넷을 하면 시계가 안 돌아가는 등의 문제가 생기겠죠.)

– 쓰레드는 한 프로세스 안에 생성되는 실행 흐름을 말합니다.

즉, 멀티 쓰레드는, 한 프로세스 안에 여러개의 쓰레드가 존재하는 것을 말하죠.

– 쓰레드는 프로세싱과 동일한 개념을 지닙니다.

다만, 프로세스 안에 존재하는 병렬적인 구성이죠.

– 원리를 알아봅시다.

일반적으로 작성되는 하나의 흐름을 지닌 프로세스는 단일 쓰레드 프로세스입니다.

코드를 해석함에 있어서, 한 코드를 위에서 부터 아래로 일직선으로 처리하기에, 만일 중간에 정보를 처리하기 위해 기다리는 부분이 있다면 아래 코드는 실행되지 않고 대기하는 상태가 되죠.

예를 들어, Scanner 객체를 이용하여, 사용자의 입력을 대기받는 기능으로 인해, 코드의 흐름이 정체된 상태라면, 그 아래로는 코드가 실행되지 않고, 프로세스가 대기중인 상태가 됩니다.

만일, 대기를 하려는 동시에 카운트다운을 하고 싶어도 단일 쓰레드로는 불가능합니다.

멀티 쓰레드는, 여러 쓰레드에 있어서 코드를 분할하여 사용됩니다.

말 그대로, 그 부분은 코드가 분할되어서 ‘병렬적’으로 동작하기에, 우리는 프로그램의 동시성을 얻을수 있게 됩니다.

구체적인 원리에 대해서는, 일단 실질적으로 작업을 처리하는 CPU 단위에서 본다면, 아예 처리하는 CPU 모듈이 복수개인, 멀티 프로세싱 CPU 코어에 의해서 작업이 물리적으로 병행될수 있고,(개인 PC에서 거의 표준으로 나오는 쿼드코어 CPU의 경우엔, CPU 연산을 처리하는 부분이 4개라는 뜻입니다. 즉, CPU 자체로도 4개의 작업을 동시에 실행할수 있죠.)

그것이 아니라, 실질적인 연산 코어가 부족한데도, 더 많은 작업을 병행하기 위해서는

‘시분할 시스템’이라는 기법을 사용하여,

CPU의 사용 시간을 각 쓰레드에 나누어 줍니다.

– 시분할 시스템 :

운영체제 과목을 공부하셨다면 아실텐데, 그냥 각 쓰레드에 CPU 자원을 나눠주는 방법을 말하는 것입니다.

현실에도, 많은 사람들이 부족한 자원을 나눠 쓸때, 몇 시 부터 몇시까지는 A가, 그리고 다음은 B가…

이런 식으로 사용 시간을 분할하는 것처럼,

컴퓨터 자원의 사용에 대하여, OS가 각 프로세스에게 ‘효율적인’ 분배를 해주는 형식으로, 번갈아가며 사용합니다.

성능이 최대한 떨어지지 않는 형태로,

최대한 빠르게 시분할을 한다면,

분할받는 각 프로세스는, 빠르게 각 자원을 사용하면서 스위칭 되며, 마치 ‘동시’에 작업을 진행하는 것처럼 보이게 될 것입니다.

(자바 병렬 처리 구현)

– 자바에서 병렬 처리 구현을 하는 것은 쉽습니다.

자바는 클래스 단위로 프로그래밍을 나누므로, 이 클래스 단위로 쓰레드를 나누어 준다고 명시하면 됩니다.

– 원하는 클래스의 Thread 상속법

public class Thread1 extends Thread{ @Override public void run() { // run()메소드를 오버라이딩 //병렬적으로 처리할 로직 작성 } }

: 우리가 쓰레드로 나누고 싶은 클래스를 Thread 클래스를 상속받아, 그 안에 선언된(정확히 말하자면, Thread 클래스가 implements 한, Runnable이 선언한) run 메소드 안에, 우리가 로직을 재정의 해주면 됩니다.

바로 이 쓰레드 클래스를 객체화 하여, 사용하면, 병렬적으로 처리되는 로직을 run() 메소드 안에 넣어주면 되는 것이죠.

사용법으론,

public static void main(String [] args){ Thread t1 = new Thread1(); t1.start(); }

이렇게 간단하게, Thread 객체를 생성하고,

그 안에 미리 병렬적으로 동작 하도록 만들어진 start 메소드를 실행시키면,

우리가 run 안에 작동시켰던 로직이 main 쓰레드와는 별개의 쓰레드로, 동시에 실행되게 될 것입니다.

만일 우리가 run 메소드 안에,

while(true)

와 같은 반복문을 사용하여도, main 쓰레드는, t1.start() 부분에서 멈추지 않고,

해당 반복문은 반복문대로, main 쓰레드는 main 대로 실행이 될것입니다.

– 쓰레드 작성 다른 방식

: 위의 방법도 좋지만, 자바에서는 extends를 하나 밖에 사용하지 못하죠?

그래서 Thread 클래스를 직접 extends 하는 것은 별로 좋지 않습니다.

대신하여, 사용되는 방법이 있습니다.

public class Thread2 implements Runnable{ @Override public void run() { // run()메소드를 오버라이딩 //병렬적으로 처리할 로직 작성 } }

위와 같이, Runnable 인터페이스를 사용하면, Thread 클래스와 같이, run 메소드를 작성할수 있습니다.

그리고 다른 상속을 사용할 때에도 불편함이 없죠.

작성은 Thread와 같이 하고,

사용시에는,

public static void main(String [] args){ Thread t2 = new Thread(new Thread2()); t2.start(); }

위와 같은 방식으로, Thread 생성자의 매개변수로, 내가 작성한 클래스를 객체화 하여 넣어주면 됩니다.

– 쓰레드 작성 간편 방식

: 람다식을 이용하여, 로직 작성과 동시에 실행을 시킬수도 있습니다.

public static void main(String [] args){ Thread thread3 = new Thread( () -> { for (int i = 0; i < 10; i++) { System.out.println(i); } }); thread3.start(); } Thread에 쓰이는 매개변수가 요구하는 메소드는 한개이기 때문에, 위와 같이 람다식을 이용하여, 즉석에서 간편하게 run 메소드를 작성해서 사용할수 있습니다. (쓰레드간 우선순위 결정) public static void main(String [] args){ Thread t1 = new Thread(new Thread1()); Thread t2 = new Thread(new Thread2()); Thread t3 = new Thread(new Thread3()); t1.setPriority(t1.MAX_PRIORITY); t2.setPriority(t2.NORM_PRIORITY); t3.setPriority(t3.MIN_PRIORITY); t1.start(); t2.start(); t3.start(); } : 쓰레드는 시분할 시스템으로, 어느 쓰레드가 먼저 실행될지에 대한 기준이 희미합니다. 기본적으로는 NORM_PRIORITY로, 같은 우선순위 끼리 같은 확률로 실행될 자격을 얻는데, 위와 같이 setPriority를 사용하면, 각 쓰레드별로 우선순위를 지정해줄수 있습니다. (주의점) - 위까지 하여, 간단하게, 자바에서 쓰레드를 나누는 방법을 알아보았습니다. 이제 여러분은, 한 코드 안에 동시적으로 실행되는 구간을 만들어 낼수 있죠. 그러나 병렬처리는 여러가지 주의점이 있습니다. - 쓰레드간 정보 : 통신이라 하니, 멀리 있는 사람에게 전화를 거는 것 같은 행위를 떠올릴 수도 있을텐데, 그냥 각 쓰레드 간에 정보를 교환하는 것을 말합니다. public class Thread1 implements Runnable{ @Override public void run() { // run()메소드를 오버라이딩 //병렬적으로 처리할 로직 작성 } } public class Thread2 implements Runnable{ @Override public void run() { // run()메소드를 오버라이딩 //병렬적으로 처리할 로직 작성 } } 위와 같이, 두 쓰레드 클래스가 있다고 해봅시다. 그렇다면, 각 클래스는 서로 다른 변수 공간과 실행 공간을 가지고 있습니다. 이 둘 사이에는 각자 다른 스코프를 가지기에, 서로 침범할수 없죠. 만일 t1과 t2가 동일한 변수를 가리키려면 어떻게 해야 할까요? 값만을 원한다면, 각 쓰레드 흐름을 가지게 되는 클래스의 매개변수로, 값을 받아와, 지역변수로 사용하는 방식이 있겠지만,(run 메소드는 오버로딩이 안되니, 생성자 매개변수를 사용해 멤버변수로 만듭니다.) 만일 동일한 메모리 공간을 참조하고 싶다면, 값을 클래스로 감싸서, 참조형 변수로 만들어주는 기법인 DTO를 사용해도 되고, 프로그램이 실행될 때부터 끝날 때까지 메모리에 올라가 있는 static 변수를 사용하여, System.out.println(Thread3.intValue); 이런 식으로 값을 사용해도 됩니다. - 병렬 프로그래밍에서 주의해야 할 점은, 바로 이런 공유 영역에 대한 처리입니다. - 공유 변수 : static을 이용하여, 쓰레드 클래스 내에서, Thread3.intValue; 이런 식으로 값을 사용하게 되면, 편하게 해당 값에 접근 및 사용이 가능하지만, 문제가 생길 여지가 있습니다. 만이 Thread1이, 지속적으로 MainClass.intValue를 print하고, Thread2가, 지속적으로 MainClass.intValue를 1씩 늘린다고 합시다. 둘은, 소위 말하는 동기화라는 것이 되어있지 않습니다. 그 말은, Thread1이 MainClass.intValue의 값이 0을 출력하고, 다음에 Thread2가 MainClass.intValue의 값을 1 증가시키는 방식으로, 순차로 실행되는 것이 아니라, 어떤 식으로 시분할 되어 병렬적으로 처리될지에 대한 기준이 없기 때문에, 가끔은 같은 값을 2,3번 print 하기도 하고, print 되지도 않은 값을 증가시키기도 합니다. 뭐, 이런 기능이야 병렬처리에서 별로 문제될 것이 없고, 시간 같은 것을 표시할 때, 일부러 이런 식으로 비동기 방식을 택하기도 하는데, 만일 은행 업무 처리 및, 쓰레드 간에도 서로 동기화된 프로세스를 실행해야 하는 경우가 있습니다. - 공유 메서드 : 마찬가지로 static을 이용하여 작성한 메서드 역시 프로그램 최초 기동시 메모리에 올라가게 되는데, 이 역시 여러 쓰레드에서 동시에 사용될수 있습니다. 그 동시성으로 인한 충돌 같은 문제가 일어나는 것을 방지하고 싶을 때도 있겠죠. - 공유 자원 : 메모리에 대한 접근이나, CPU 와 같은 하드웨어 자원의 사용에 대하여, 공유되는 부분이 있습니다. 이 역시 여러 쓰레드가 동시에 요청을 하게 되면 여러모로 문제가 발생할수 있습니다. - 공유 변수 해결 : 여기서는 파생 지식까지 자세히 말씀드리지는 않겠습니다. 병렬 프로그래밍의 부분은 따로 자세히 정리할텐데, 키워드만 말해두자면, 세마포어와 뮤텍스라는 것이 있습니다. 그것을 사용하여 공유 공간에 대한 관리가 가능한데, 자바에서는 아주 간단하게 쓰레드간 공유 영역에 대한 동기화를 해주는 방법이 있습니다. [synchronized 키워드] - 아주 간단합니다. 여러 쓰레드가 동시에 실행하는 것을 막고자 하는 메소드나 블록에 synchronized 키워드를 붙이면 됩니다. - synchronized 메소드 public static synchronized add(){ } : static이고 아니고 상관이 없습니다. 여러 스레드가 해당 메소드를 사용하고자 할 때, 순차적으로 접속할수 있도록 동시 접속을 막아놓는 키워드 입니다. 그냥 synchronized가 붙은 메소드는, 한 번에 하나의 스레드만이 사용 가능하다고 알아두세요. 그러니 싱글 스레드 상태에서 붙여놓아도 별 상관이야 없겠죠. 만약 synchronized를 붙이지 않은 메소드를 쓰레드가 공유하여 사용한다면, 쓰레드 안의 상태, 즉 변수 값이 도중에 바뀌어 버릴수도 있습니다. Thread1은 add 안의 변수값을 1로 변형시키고, 마지막에 출력하려 했는데, 나중에 들어온 Thread2가 이 변수값을 2로 변형시킨다면, Thread1이 출력하는 값은, 의도한 1이 아닌 2가 되는 것이죠. 그렇기에 이렇게 synchronized를 사용하면 한 쓰레드가 해당 메소드를 사용하는 도중에, 다른 메소드가 이곳에 침범할수 없게 됩니다. 주의할 점은, synchronized 메소드의 경우는, 해당 메소드 뿐만 아니라, 해당 메소드를 가지고 있는 '객체'에도 Lock이 걸린다는 점을 명심하세요. 그러니까, synchronized 메소드가 사용하는 클래스의 멤버변수 역시 다른 스레드가 침범하지 못한다는 뜻이고, 해당 메소드를 품고 있는 객체 자체에 lock을 거는 것입니다. - synchronized 블록 : 위와 같이 내가 원하는 부분만이 아니라 객체 자체에 lock이 걸리게 하고 싶지는 않은 경우가 있을수 있습니다. 어느 부위에만 synchronized를 적용하는 방법이 바로 synchronized 블록입니다. public void add(int val) { /* * Code for synchronization is not needed * */ synchronized(this){ //동기화 할 부분 } } } 위와 같이, 클래스 내부 구역 어디든, synchronized 키워드를 위와 같이 사용하여 블록을 형성하면, 해당 블록 내부 구역은, 쓰레드간 동기화가 되는 것입니다. - synchronized 블록의 매개변수 : 위와 같이, synchronized 블록을 이용하면, 매개변수를 넣어줘야 합니다. 이 매개변수는 Object 타입입니다. this도 Object이므로 상관 없죠. 그런데, 이 매개변수가 어떤 일을 할까요? 저도 자세히 설명은 못합니다. 그저 이 파라미터로 들어오는 객체의 공간을 공유한다고 생각해 주세요. 해당 블록 안에 사용되는 자원을 품은 객체를 넣어주면 됩니다. class B { public void meth() { for(int i=0;i<3;i++) { System.out.println(Thread.currentThread()+" " + i); } } } class A implements Runnable { B obj; A(B ob) { obj=ob; } public void run() //Entry point of the thread. { //Synchronized block synchronized(obj) //synchronizing the object of B class { obj.meth(); //call to meth() is synchronized } } public static void main(String... ar) { B ob= new B(); A thread1= new A(ob); A thread2= new A(ob); Thread t1= new Thread(thread1, "Thread1"); Thread t2= new Thread(thread2, "Thread2"); //Calling Thread's constructor & passing the object //of A class that implemented Runnable interface //& the name of new thread. t1.start(); t2.start(); } } : 위와 같이, B 클래스가 synchronized 블록의 매개변수로 들어가며, 해당 객체가 synchronized 되는 것이죠.(https://www.decodejava.com/synchronized-block-in-java.htm) synchronized의 경우는 https://tourspace.tistory.com/54 를 추천합니다. (기타) - 현재 진행중인 쓰레드 정보 가져오기 : Thread 객체의 메소드로, 사용중인 쓰레드 정보를 가져올수 있습니다. Thread.currentThread().getName() - 메인 쓰레드도 결국은 쓰레드 입니다. 각 쓰레드는, 일단 시작되면 독립된 시행을 보내는데, 이는 메인 쓰레드가 종료되더라도 독립 쓰레드가 종료되지 않는 것을 뜻합니다. 만일 메인 쓰레드가 종료됨과 동시에, 포함되는 각 쓰레드들을 모두 종료시키기 위해서는, public static void main(String [] args){ Thread t1 = new Thread(() -> {while(true){}}); t1.start(); t1.setDaemon(true); }

위와 같이, .setDaemon(true); 메서드를 실행시켜주면 됩니다.

.setDaemon(true); 메서드는, 해당 스레드를 데몬 스레드로 만들어주는 메서드입니다.

다시한번 데몬 스레드에 대해서 설명하자면, 다른 비 데몬 스레드에 기생하여, 해당 비 데몬 스레드가 종료됨과 동시에 종료되는 스레드를 말하죠.

[volatile 키워드]

– 자바 volatile 키워드는 자바 코드의 변수를 ‘메인 메모리에’ 저장 및 활용 할 것을 명시하기 위해 쓰입니다.

정확히 말해서, 모든 volatile 변수는 컴퓨터의 메인 메모리로부터 읽히고, volatile 변수에 대한 쓰기 작업은 메인 메모리로 직접 이루어집니다. ( == CPU 캐시가 쓰이지 않습니다.)

– 자바 코드 최적화에 대해 논해보죠.

만약 우리가 int a = 10; 이라고 변수를 만들었다고 합시다.

어느 프로그램이라도 그렇듯, 하드웨어에 저장된 정보는, 메모리 공간 위에 올라가고, 메모리 공간 위에 저장된 정보 역시, 요청을 받으면, CPU 내부의 작은 저장 공간인 레지스터로 이동하게 됩니다.

하드웨어에서 메모리로 정보가 올라가는 데에도 시간이 많이 걸리지만,

메모리에서 CPU로 정보가 넘어가는데 드는 시간도 있죠.

그렇기에 CPU에서는 캐싱이라는 기법을 사용합니다.

잘 쓰일것 같은 정보들을 CPU 내부 메모리에 저장해두고 사용하는 것으로,

이렇게 하면, 메모리에서 값을 받아오는데 들이는 시간을 줄일수 있죠.

자바의 바이트 코드는 JVM에 의해서 이러한 최적화 과정을 거칩니다.

-하지만 오히려 이러한 최적화가 방해가 되는 경우가 있습니다.

자, 한번 봅시다.

한 프로그램에서 변수 a를 생성했습니다.

이것을 그냥 사용시, 처음 한번은, 메모리에서 CPU로 값이 이동할 것입니다.

그리고 특별히 일이 없을 때에는 이 변수의 값이 사용되지 않을 것이기에 캐시 메모리에서 대기를 합니다.

그런데, 메인 쓰레드와는 또 다른 새로운 쓰레드가 생겨나, 이 a라는 변수를 참조하기 시작했다고 합시다.

해당 메모리에 대해, t1 쓰레드가, a의 값을 1에서 2로 바꿨습니다.

그러면 메인 쓰레드가 이 a의 값을 읽으려 할때, 무슨 값이 찍힐까요?

우리는 최근에 바뀐 2라는 값이 되리라고 예상하겠지만,

실제로 메인 쓰레드의 값은 변하지 않습니다.

같은 변수를 사용하는데 왜 이런 결과가 나올까요?

바로 캐싱 때문입니다.

변수 a가 처음 쓰레드로 인해, CPU의 1코어에 캐싱 되었다면, 메인 쓰레드는 바로 그 1코어의 캐시 메모리를 확인하고 있을테고,

새롭게 나타난 t1 쓰레드가 CPU의 2코어에서 실행된다고 가정하면, t1 쓰레드는 2코어의 캐시 메모리를 사용하기 때문에, 서로간에 차이가 발생하는 것입니다.

이를 가시성 문제라고 하며, 한 쓰레드의 변경이 다른 쓰레드에게 보이지 않는 경우를 말합니다.

실제 하드웨어 적으로 격리된 CPU 공간을 사용하기 때문이죠.

– 위와 같은 상황을 방지하기 위한 키워드가 바로 volatile입니다.

public volatile int counter = 0;

이렇게 사용하며,

해당 변수를 사용하려면 무조건 캐시를 사용하지 말고 메모리에서 가져와 써라! 라는 의미입니다.

안정성을 위하여 병렬 프로그래밍 등에서 최적화를 금지하는 키워드죠.

(C언어에서도 최적화에 대한 반대 키워드로 사용되니 참고하세요.)

멀티 스레드 병렬 프로그래밍을 하기 전 반드시 읽어야할 것들 – Java 객체 편(객체 동기화, 클래스의 쓰레드 안정성)

반응형

JAVA 멀티 스레드 환경에서 “객체”를 다루기 전 알아야 할 것들

제목은 거창하지만 내용이 빈약할 수 있음을 미리 알립니다…

java.util.concurrent 패키지 내용을 정리하려고 하다가 기본 지식이 부족하다 생각하여 JAVA 병렬 프로그래밍이라는 책을 읽고 멀티 스레드 프로그래밍 환경에서 “Thread-safe”하게 만드는 기본 지식을 정리한 것입니다.

+ 스레드에 대한 어느정도 지식, 경험이 있는 분들이 보기 좋습니다. (초급 개발자 정도? 중급이상은 볼 필요가 없을 겁니다…)

스레드 안정성(Thread-safe)

: 여러 스레드가 어떤 변수나 함수 또는 클래스 객체에 접근할 때 계속해서 개발자가 의도한대로 정확하게 동작하하다는 것로 정의한다. 호출하는(사용하는) 쪽에서 특별한 동기화 코드 없이도 정확하게 동작하는 것이다.

멀티 스레드의 궁극적인 목표가 스레드 안정성을 가지면서 성능은 최대한 뽑아낼 수 있게 하는 것이다.

그 중에서 가장 기초가 되는 변수!(객체!) 를 thread-safe하게 만들기 위해 생각해야할 것들을 아래에 나열했다.

– 단일 연산

: 어떤 스레드A가 작업 A’를 실행 중일 때 다른 스레드B가 하는 작업 B’를 완전히 수행되었거나 전혀 수행되지 않는 두 가지 상태로만 파악된다면 A작업 입장에서 작업 B는 단일 연산이다.

즉, 외부에서 어떤 연산을 봤을 때, 완료 또는 실패로만 결과가 나오면 단일 연산이라는 것이다.

ex) a = b++; 를 봤을 때 동기화가 안되었다면 b를 증가하는 연산(b++)과 a에 대입하는 연산(a=…)이 두 개가 있으므로 단일 연산으로 볼 수 없다. (해당 연산이 동기화가 되었다면 외부에서 성공과 실패로 나뉘므로 단일 연산이다)

* 객체보단 함수(?)편에서 다뤄야 할 내용같긴 하다..

– 상태 관리를 위해 스레드에 안전한 객체를 사용하자

java.util.concurrent.atomic 패키지 안에 있는 객체들을 사용하면 도움이 된다.

atomic클래스 안에 있는 클래스들은 CAS(compare-and-swap)방식을 사용해서 스레드에 안전하다.

CAS방식은 자신이 읽었던 변수의 값을 기억하고 있다가 변경을 완료하기 직전에 읽었던 변수의 값이 그대로인지 확인하고 아니라면 실행을 무산시키는 방식이다.

이 방식은 CPU에 의해 직접 지원되는 부분이라 안심하고 사용할 수 있다.

ex) AtomicIntegerArray,길이가 100인 배열의 값을 읽어서 변경하고 있는데 다른 스레드가 와서 변경하는 경우

ex2) AtomicLong 사용하기 Long타입은 64bit중 32bit씩 변경하는 연산이 들어가서 2번 연산이 된다고 한다. (정확한지는 아직 모름.. 추측상 64bit cpu에서는 1번 연산하지 않을까함..) 따라서 long 타입으로 timestamp를 찍을 때 멀티 스레드 환경에서 동기화가 안되어있다면 변경될 가능성이 있다.

– 암묵적인 락(lock)

Mutexes, mutual exclusion lock, synchronized는 한 번에 한 스레드만 특정 락을 소유할 수 있다.

락으로 보호되고 있다는 사실은 @Guarded 같은 애노테이션을 써서 표시하면 유지보수에 도움될 수 있다.

또한 값을 쓸 때(setter)만 동기화 해야 한다는 생각은 버려야 한다.

최대한 캡슐화를 열심히 하고 변수에 접근하는 모든 메소드에서 해당 변수에 동기화 처리를 해줘야한다.

– synchronized 블록을 너무 잘게 쪼개는 것도 안 좋다.

– 오래 걸리는 연산, 네트워크, IO작업은 웬만하면 Lock을 걸지 말아야 한다. (성능 문제가 심각해질 수 있음)

– stale data(=최신 값이 아닌 과거 데이터) 주의하기

아까 AtomicLong과 마찬가지로.. long이나 double형의 64bit 값에는 메모리에 쓰거나 읽을 때 두 번의 연산이 일어나기 때문에 volatile 키워드를 써줘야 한다.

참고로 volatile 키워드로 선언된 변수 값을 바꾸면 다른 스레드에서 항상 최신 값을 읽어갈 수 있다.

단, 작은 부분이라도 가시성을 추론해봐야할 때는 사용하면 안된다.

보통 중요 이벤트가 발생했다는 정보를 정확하게 전달하고자 할 때 사용하는 것이 효과적이다.

– 클래스 생성 메소드에서 this 변수가 외부에 노출되지 않도록 해야한다.

보통 생성 메소드에서 쓰레드를 새로 만들어서 시작시키는 코드를 만들면 그런 일이 발생한다.

그 경우 쓰레드가 this를 마음대로 접근할 수 있는 상황을 만드니 조심해야한다.

쓰레드 생성까지는 문제가 없지만 동시에 시작시키는 일까지 하는 것을 주의해야 한다.

생성 메소드에서 이벤트 리스너를 등록하거나 꼭 스레드를 시작시켜야 한다면 팩토리 메소드 생성자를 통해 진행하는 것이 좋다.

– 객체가 불변이라는 것과 참조가 불변이라는 것을 반드시 구분해서 사용해야 한다.

private을 쓰듯 나중에 굳이 변경될 일이 없는 변수들은 final 키워드를 사용하는 것이 좋다.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class Point { private int x; private int y; public int getX() { return x; } public void setX( int x) { this .x = x; } public int getY() { return y; } public void setY( int y) { this .y = y; } public Point( int x, int y) { super (); this .x = x; this .y = y; } public static void main( String [] args) { final Point p = new Point( 1 , 2 ); System . out . println (p.getX() + “,” + p.getY()); //1,2 p.setX( 2 ); p.setY( 4 ); System . out . println (p.getX() + “,” + p.getY()); //2,4 p = null ; //compile error } } Colored by Color Scripter

예제에서 볼 수 있듯 Point객체는 불변하게(final) 되어있지만 내부에 있는 변수들은 변경될 수 있다. 엄연히 다른 것이다.

– 객체를 공유해 사용하고자 할 때 원칙

1. 스레드 내부에 존재하면서 해당 스레드에서만 사용한다.

2. 읽기 전용 객체를 공유한다. 즉, 불변 객체를 이용한다.

3. 스레드에 안전한 객체를 공유한다. 객체 내부적으로 필수적인 동기화 기능이 이미 구현되어 있는 객체가 이에 해당한다.

4. 특정 객체에 동기화 방법을 적용해두면 지정한 락(Lock)을 획득하기 전에는 사용할 수 없다.

– 객체 지향에 맞게 객체가 갖고 있는 정보를 객체 내부에만 잘 두면 객체 단위로 스레드 안정성을 확보하기만 하면 다른 것을 고려하지 않아도 되기 때문에 좋다.

+ 객체 상태를 보관하는 변수가 무엇이 있는지 확인한다.

+ 객체 상태를 보관하는 변수가 어떤 종류인지, 어떤 범위를 갖는지를 확인한다.

+ 객체 내부의 값을 동시에 사용하려고할 때 그 과정을 관리할 수 있는 정책을 확인한다.

– 어떤 동작을 실행하기 전에 특정한 조건을 만족할 때까지 기다리도록 프로그래밍하고자 한다면 wait, notify 대신 세마포어나 블록킹 큐와 같은 라이브러리를 쓰는 것이 안전하다.

– 동기화 정책 문서화하기 (사람끼리 동기화)

– 동기화된 컬렉션 사용하기?

Vector나 hashtable같은 컬렉션을 사용한다.

주의할 점은 반드시 컬렉션에서 제공되는 메소드로 추가 또는 제거등의 기능을 사용해야 한다.

– 반복문 전체에 동기화를 거는 방법은 지양해야한다.

반복문 전체에 동기화를 걸어버리면 컬렉션 안에 값들이 얼마나 들어있을지 모르고 그 안에서 다른 lock이 걸리면 데드락이 걸리는 최악의 상황도 생긴다. (iter.next()로 반복하는 중간에 값이 변경될 수 있음 concurrentModificationException)

이럴 때는 clone()메소드로 사본을 만들어서 사용하면 그 스레드에 한정되어 있으므로 문제를 해결할 수 있다.

물론 clone()할 때는 동기화 해야한다.

– 더 나아진 병렬 컬렉션 사용하기

동기화된 컬렉션의 사용은 동시성에 손해가 컸다. (반드시 1개의 쓰레드만 사용하게 되어있었으니…)

여기서 말하는 병렬 컬렉션은 ConcurrentHashMap과 같은 것들이다. (java.util.concurrent패키지에 있는 클래스)

put-if-absent, replace, conditional remove등의 연산을 사용한다.

병렬 컬렉션은 락스트라이핑이라는 굉장히 세밀한 동기화 방법을 사용해서 여러 스레드에서 공유하는 상태에 더 잘 대응할 수 있다.

참고로 ConcurrentHashMap같은 것은 ConcurrentModificationException을 만들지 않는다.

대신 병렬 컬렉션을 쓰면 size나 isEmpty()메소드 같은 것들은 의미가 퇴색된다. (정확한 값이 아니기 때문)

결과를 추정할 수 있는 정도로 쓰면 된다.

물론 치명적이지 않으니 걱정할 정도는 아니다.

ConcurrentHashMap의 단점이 없을까? 아니다 Map을 독점적으로 사용해야 하는 경우가 있을 때는 사용하면 피곤해진다.

– blockingQueue를 사용하면 생산자 – 소비자 구조에서 생산자가 엄청나게 생산하는 것을 방지할 수 있다. (생산자가 큐 사이즈이상으로 생산하려고 할 때 lock을 걸어주기 때문.)

– 동기화 클래스 사용하기

+ Latch

Latch는 1회용이다. CountDownLatch의 경우 Latch는 lock을 걸 count를 만들고 코드에서 latch를 만나는 부분에 들어오는 모든 쓰레드들을 못 지나가게 막다가 지정한 count가 0이되면 막혀있던 스레드들을 풀어준다.다. 대신 한 번 열리면 계속 열려있게된다. 다시 안막음!

+ FutureTask

FutureTask도 래치와 비슷하다.

Callable 인터페이스를 구현하도록 되어있다. 시작 전 대기, 시작됨, 종료 3가지 상태로 구분할 수 있고 한번 종료상태가 되면 더 이상 상태가 바뀌는 일은 없다.

(java.util.concurrent패키지를 정리하며 CompletableFuture 부분에서 다시 설명할 기회가 있을 것 같다.

Future.get()메소드는 FutureTask의 작업이 종료되면 그 결과를 즉시 알려준다.

보통 FutureTask의 경우 실제 결과가 필요한 시점보다 훨씬 이전에 시간이 많이 필요한 작업을 미리 해두는 용도로 사용한다.

+ 세마포어

특정 자원이나 특정 연산을 동시에 사용하거나 호출할 수 있는 스레드의 수를 제한할 때 사용한다.

남은 퍼밋(Permit)이 없는 경우 acquire()메소드를 사용하면 퍼밋이 생기거나 인터럽트가 걸리거나 타임아웃이 걸리지 전까지 대기한다.

release()메소드는 확보했던 퍼밋을 다시 세마포어에게 돌려주는 메소드다.

+ barrier

latch와 유사하게 barrier가 있는 코드에 접근하는 쓰레드들을 해당 count만큼 막고 있다가 풀어준다. 대신 1회성이 아니라 다시 지정한 개수의 barrier를 만들어서 또 스레드들을 막는다.

latch는 이벤트를 기다리는 동기화 클래스고 barrier는 다른 스레드를 기다리는 동기화 클래스다.

모든 쓰레드가 배리어 위치에 이르러야 진행이 가능하다.

+ Exchanger

Exchanger는 두 개의 쓰레드가 연결되는 barrier다.

barrier 포인트에 도달하면 양쪽의 스레드가 서로 갖고 있던 값을 교환한다.

양쪽 스레드가 서로 대칭되는 작업을 수행할 때 유용하다.

* 요약

객체의 상태를 나타내는 변수가 바뀔 수 있음을 인지한다.

병렬성과 관련된 모든 문제점은 “변수”에 접근하려는 시도에서 나온다는 것을 인지한다.

변경 가능한 값이 아닌 변수는 모두 final을 쓰는 것을 권장하고

변경 가능한 부분은 lock을 걸어서 동기화 시킨다.

동기화가 필요없는 부분은 버린다.

틀린 부분이 있으면 지적바랍니다. 꼭이요.. (저를 포함한 모두에게 도움이 됩니다!)

출처 :

JAVA 병렬 프로그래밍 – 책

http://aroundck.tistory.com/

반응형

멀티코어를 100% 활용하는 자바 병렬 프로그래밍

주문제작 상품 구매안내

해당상품은 고객님의 주문사항에 맞춰 제작되는 상품이므로 판매자의 의사에 반하여 취소 및 교환, 반품이 불가능 합니다. (상품하자시 제외)

이에 동의하시는 경우 동의버튼을 선택해 주세요.

키워드에 대한 정보 자바 병렬 프로그래밍

다음은 Bing에서 자바 병렬 프로그래밍 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.

이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!

사람들이 주제에 대해 자주 검색하는 키워드 프로세스는 뭐고 스레드는 뭔가요?

  • 프로그래밍
  • programming
  • process
  • thread
  • multithreading
  • 스레드
  • 쓰레드
  • 프로세스
  • 멀티쓰레딩
  • 멀티스레딩
  • 동시성
  • 병렬성
  • synchronized
  • 멀티태스킹

프로세스는 #뭐고 #스레드는 #뭔가요?


YouTube에서 자바 병렬 프로그래밍 주제의 다른 동영상 보기

주제에 대한 기사를 시청해 주셔서 감사합니다 프로세스는 뭐고 스레드는 뭔가요? | 자바 병렬 프로그래밍, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.

Leave a Comment