자세한 성능 동시 프로그래밍 자바

I. 서론

이 문서에서는 다중 스레드 응용 프로그램의 성능에 초점을 맞추고 있습니다. 에 의한 기술의 방법은 잠금 경합을 줄이기 위해, 및 구현하는 코드를 사용하는 방법에 대해 설명합니다.

둘째, 성능

우리 모두는 멀티 스레드 스레드의 성능을 향상시킬 수 있음을 알고있다. 성능의 근본 원인은 우리의 멀티 코어 CPU 또는 여러 CPU에있다. 작은 일련의 작업 프로그램의 전반적인 성능을 향상시킬 수 서로 독립적으로 실행할 수 있습니다에 큰 작업에 각각의 CPU 코어는 작업 자체를 완료 할 수 있습니다. 예를 줄 수, 수정되는 등 하드 드라이브 폴더에있는 폴더의 모든 이미지의 크기와 같은 프로그램이 있습니다, 멀티 스레딩 기술하여 성능을 향상시킬 수 있습니다. 우리는 CPU 코어의 이상이있는 경우 단일 스레드 방식의 사용은, 수정을 모든 사진 파일을 설정하고 수행 할 수 있습니다, 다음, 의심의 여지가, 그것은 단지 그들 중 하나 개의 코어를 사용할 수 있습니다. 접근 방식을 멀티 스레드, 우리는 생산자 스레드가 큐에 추가되는 각 사진에 파일 시스템을 검사 할 수 있으며, 다수의 작업자 스레드 이러한 작업을 수행합니다. 수와 우리의 작업 단어의 같은 수의 총 CPU 코어 스레드, 우리는 작업이 완전히 구현 완료 될 때까지 각각의 CPU 코어가 할 수있는 생활이 있는지 확인 할 수 있습니다.

다른 프로그램이 더 IO 대기를 필요로 들어, 멀티 스레딩 기술의 사용은 전체 성능을 향상시킬 수 있습니다. 우리는 이러한 프로그램을 작성한다고 가정, 당신은 사이트에있는 모든 HTML 파일을 잡아해야하고, 로컬 디스크에 저장합니다. 프로그램은 그렇게 다시하고 다시하고,이 사이트를 가리키는 모든 링크이 페이지를 구문 분석이 링크를 크롤링 설정, 특정 웹 페이지에서 시작할 수 있습니다. 우리는 페이지가 몇 시간 동안 기다릴 필요가 모든 데이터를 수신 할 수있는 원격 사이트에서 요청을 시작, 그렇게 때문에 우리는 여러 스레드를 실행하기 위해이 작업을 사용할 수 있습니다. 하자 조금 더 또는 HTML 페이지와 링크를 구문 분석하는 수신 된 약간의 스레드가 큐에서 찾을 수 스레드는 다른 모든 요청 페이지에 대한 책임이 있습니다.

고성능 짧은 시간 창에 많은 일을하는 것입니다. 이것은 확실히 성능 기간의 가장 고전적인 해석이다. 그러나 동시에, 스레드의 사용은 우리의 프로그램의 속도를 향상시키기 위해 잘 반응 할 수 있습니다. 이러한 GUI 애플리케이션 상상해 아래 입력란 상기 입력 박스 "처리"버튼라는 이름을 가지고있다. 및 시작하는 사용자의 입력을 처리하는 사용자가 버튼을 누르면, 어플리케이션이 버튼의 상태를 다시 렌더링해야 (시간 및 반발 할 때 버튼을 누른 것으로 보이는, 마우스 버튼을 해제). 사용자 입력의 시간이 소요되는 작업을 다루는 경우, 단일 스레드 프로그램이 다른 사용자의 입력 작업에 응답 계속할 수 없습니다,

얻을 수있다 높은 성능을 가산함으로써 계산 자원 : 확장 (확장)는 프로그램 할 수있는 기능을 포함하는 것을 의미한다. 우리가 우리의 기계의 CPU 코어의 수는 제한되어 있기 때문에, 사진을 많이의 크기를 조정해야하므로 항상 성능 증가를 해당 스레드의 수를 증가하지 않는 상상해보십시오. 반대로, 스케줄러의 요구와 스레드를 생성하여보다 많은 책임이 있기 때문에, CPU 자원을 차지하지만, 성능이 저하 될 수 있습니다.

성능에 1, 영향

더 많은 스레드를 추가하면 프로그램의 성능과 응답 성을 향상시킬 수 있습니다 : 우리는 이러한 관점을 만들었습니다, 당신에게 물품. 그러나 다른 한편으로는, 우리는 이러한 혜택은 쉽지 않았다 싶어뿐만 아니라 가격을 지불해야합니다. 스레드를 사용하여 성능 향상에 영향을 미칠 것입니다.

우선, 처음으로 만든 나사의 영향. 스레드의 생성은 기본 운영 체제에서 JVM은 적절한 리소스를 적용하고, 실행 스레드의 순서를 결정하기 위해 스케줄러의 데이터 구조를 초기화 할 필요가있다.

코어의 동일한 수와 CPU의 수, 다음 스레드가 각 스레드가 하나 개의 코어에서 실행되는 경우, 그래서 어쩌면 그들은 종종 중단되지 않습니다. 프로그램을 실행하면 그러나 사실, 운영 체제는 CPU 처리에 자신의 작업의 일부를해야합니다. 그래서,이 경우에도, 스레드가 중단하고 그것의 작동을 재개하기를 기다립니다. 스레드의 전화 번호는 CPU의 코어 수를 초과하는 경우, 상황은 더 악화 될 수 있습니다. 이 경우, JVM 프로세스 스케줄러가 다른 스레드, 스레드 스위칭 시간을 허용하는 일부 스레드가 중단됩니다, 실행중인 스레드의 단지 현재의 상태는 다음 실행을 복원 할 수 있도록하는 경우, 보존 할 필요가 데이터 상태를 표시합니다. 뿐만 아니라, 스케줄러는 자신의 내부 데이터 구조를 업데이트 할 것이며,이 CPU 사이클을 소모한다. 이 모든 스레드 사이에서 스위칭 문맥 CPU 컴퓨팅 자원을 소비 수단이므로, 단일 스레드의 경우에 비해 더 성능 오버 헤드를 가져 오지.

멀티 스레드 프로그램의 공유 데이터에 동기 액세스로부터 보호 다른 오버 헤드를 가져왔다. 우리는 여러 스레드간에 데이터를 공유 할 수 휘발성 키워드를 사용할 수 있습니다 보호를 동기화하는 동기화 된 키워드를 사용할 수 있습니다. 하나 개 이상의 스레드가 특정 공유 데이터 구조에 액세스하려고하면, 상황은 경합, 다음, JVM 프로세스가있는 후 공정, 처음으로 결정해야 발생했습니다. 당신이 스레드가 스레드가 현재 실행되는 실행되지 결정하는 경우, 스레드 스위칭이 발생합니다. 성공적으로 잠금 객체를 얻을 때까지 현재 스레드가 대기. 그것은이에 성공할 때까지 JVM은 잠금 개체를 얻으려고 계속의 JVM은 비교적 짧은 시간, 당신은 예를 들어, 급진적 인 방법을 기다리 JVM을 사용할 수있는 성공적인 락 객체에서 예상되는 경우,이 "대기"를 수행하는 방법을 스스로 결정할 수 있습니다 이 방법의 경우는,보다 효율적으로 할 수 있기 때문에보다 신속하게이 방법의 일부를했다 비교 프로세스 컨텍스트 스위치. 스레드는 또한 추가 비용을 가져올 것 다시 큐의 구현의 상태로 이동을 기다리고 있습니다.

따라서, 우리는 잠금 스위치로 인해 초래 경쟁의 상황을 피하기 위해 시도해야합니다.

이번 대회는 모두 감소 발생 다음과 같은 과정을 설명 할 것이다.

2, 잠금 경합

두 개 이상의 스레드에 액세스하기위한 경쟁은 경쟁이 급진적 상태를 입력하거나 상태가 두 개의 컨텍스트 스위치를 야기 기다릴 수 있도록 대기 스레드를 만들기 위해 스케줄러를 강제로 수행되므로, 추가 운영 오버 헤드를 가져올 것이다 잠급니다. 잠금 경합 결과 다음과 같은 방법으로 완화 될 수있는 몇 가지 경우가 있습니다 :

1. 개요 이하 잠금;

2. 필요한 주파수 획득 이하 잠금;

3. 하드웨어 지원 관적 잠금 동작에 의해 사용되는 양은, 동기화되지;

동기 4. 이하;

사용 적은 개체 캐시

  

2.1 감소 동기 필드

  코드 잠금, 필요 이상으로 유지하면 첫 번째 방법은 적용 할 수 있도록. 보통 우리는 현재의 스레드가 잠금 시간을 보유하고 줄이기 위해 동기화 영역 중 코드의 하나 개 이상의 라인이 될 수 있습니다. 적을 동기화 영역에서 실행되는 코드의 수, 빨리 다른 스레드가 이전에 잠겨받을 있도록 현재의 thread가, 잠금을 해제 것이다. 그렇게하는 당신이 실행을 동기화해야하는 코드의 양을 줄일 수 있기 때문에, 암달의 법칙과 일치한다.

2.2 분할 잠금

로크 경합을 감소시키기위한 또 다른 방법은 보호 작은 복수의 블록으로 로크 보호 된 코드이다. 프로그램이 다른 개체의 수를 보호하기 위해 잠금을 사용하는 경우,이 방법은 쓸모가있을 것입니다. 우리는 프로그램을 통해 데이터의 개수를 카운트 할, 다른 통계적인 지표들을 보유하는 클래스의 단순한 카운트를 구현한다고 가정하고, 염기성 카운트 변수 (롱 타입)을 나타내는 데 사용되었다. 우리의 프로그램이기 때문에 멀티 스레드, 그래서 우리는 이러한 변수 동기화로 작동 액세스해야하는 다른 스레드에서 이러한 운영 작업을하기 때문이다. 이를 위해 가장 쉬운 방법은 동기화 키워드를 추가하는 기능으로 각 변수를 방문하는 것입니다.

2.3 분리 잠금

위의 한 예는 각 스레드는 그들에게 당신이 그것을 수정하려는 개체를 잠글 수 있도록 단일 잠금, 개별 잠금 장치로 분리하는 방법을 보여줍니다. 구현이 올바른 단어는 교착 상태가 발생할 수없는 경우 그러나 다른 한편으로는,이 방법은, 프로그램의 복잡성을 증가시킨다.

스핀 로크를 분리하면 로크 동일한 방법이지만, 회전 잠금을 늘리면 코드 또는 객체하지만 다른 범위의 값을 보호하는 다른 분리 자물쇠 잠금을 사용하는 다른 부분을 보호 할 수있는 잠금 장치이다. JDK를 ConcurrentHashMap의의 java.util.concurrent의 패키지는이 아이디어의 사용은 HashMap의 프로그램에 크게 의존하는 사람들의 성능을 향상시킬 수있다. 구현에서, 내부 ConcurrentHashMap의 대신 동기 보호되는 HashMap의 패키지의 다른 로크 (16)를 사용. (16)은 각각의 비트 버킷 16 점 (통) 중 하나에 대한 액세스를 동기화 보호 담당 잠금. 그 결과, 다른 스레드 당신은 적절한 조치를 보호하기 위해 다른 잠금 될 것입니다 시간의 다른 세그먼트에 키를 삽입 할. 그러나 다시 같은 특정 작업의 완료로 나쁜 문제가 지금 여러 잠금 장치보다는 잠금을 획득 할 필요가 나타납니다. 당신이 전체지도를 복사 할 경우, 그 16 잠금 완료해야합니다.

2.4 원자 조작

또 다른 방법은 원자 작업을 사용하여 잠금 경합을 줄이는 것입니다. java.util.concurrent의 패키지는 일반적인 기본 데이터 형 원자 작업은 클래스 패키지를 제공합니다. 원자 클래스 기반 프로세서가 "교체 비교"기능 (CAS), CAS 작업은 업데이트 작업을 제공 할 것입니다 운영 시간 레지스터의 현재 값의 이전 값과 동일을 제공 얻을 수 있습니다.

이 원칙은 변수의 값을 증가하는 긍정적 인 방법으로 사용할 수 있습니다. 우리는 스레드의 현재 값을 알고 있다면, 그것은 CAS 작업의 사용을 증가하기 위해 작업을 수행 할 것입니다. 다른 스레드는 변수의 값 중에 수정 된 경우, 소위 스레드의 현재 값은 실제 값으로 제공되었습니다 성공 될 때까지 반복적으로, 현재 값을 얻기 위해 시도하고 다시 시도 후, JVM 동일하지 않습니다 . 자전거는 일부 CPU 사이클,하지만 일의 장점을 낭비 할 수 있지만 그래서 우리는 동기 제어의 어떤 형태를 필요가 없다는 것입니다.

2.5 핫스팟 니펫을 피하기

전형적인리스트리스트는 자체에 포함 된 소자의 수 함량 변수를 유지하고 기록 삭제하거나 해당 변수의 값을 변경할 때리스트에서 모든 요소를 ​​추가 달성한다. 단일 스레드 애플리케이션 LIST 단어에 사용하는 경우,이 이해하게는, 크기에 대한 각 호출 라인에 (전회 산출 값은 이후에 직접 반환)한다. 내부 변수리스트가 유지되지 않으면,이 수, 각각의 크기 () 호출 동작 LIST 요소 수를 계산 - 반복 처리를 다시 초래할 것이다.

이 많은 데이터 구조는 문제가 될 Shique 멀티 스레드 환경, 방법을 최적화하는 데 사용됩니다. 우리가 여러 스레드 사이에서 목록을 공유 가정하면, 여러 스레드가 동시에 행방을 추가하거나 LIST 내부 요소를 제거, 큰 길이를 조회 할 수 있습니다. 이 때, 내부 카운트 변수 목록은 그래서 모든 액세스가 동기화되어야하며, 공유 자원이된다. 따라서, 전체를 핫 카운트 변수 LIST 구현된다.

이 문서에서는 다시 한 번 이러한 프로그램의 최적화를 설명하는 최적화 각각의 실시간 애플리케이션에서주의 관찰을 많이 필요로 뭔가 보여줍니다. 최적화 조기 표면은 매우 합리적인 것처럼 보이지만, 실제로 성능 병목 현상이 켜 가능성이 높습니다.

추천

출처blog.51cto.com/14512197/2444199