이 기사를 읽기 전에 먼저 " Java Multithreaded Atomic 패키지의 소개 및 사용 " 을 읽고 Atomic 패키지의 관련 내용에 대해 알아볼 수 있습니다.
1. 원자력이란 무엇입니까?
Atomic이라는 단어는 원자와 관련이 있으며, 한때 가장 작은 물질의 단위로 간주되었습니다. 컴퓨터의 원자는 여러 부분으로 나눌 수 없다는 것을 의미합니다. 코드 조각이 원자가로 간주되면 실행 중에 코드를 중단 할 수 없음을 의미합니다. 일반적으로 원자 지침은 하드웨어에 의해 제공되며 소프트웨어가 원자 메소드를 구현하기 위해 제공됩니다 (실행이 완료 될 때까지 메소드를 입력 한 후 스레드가 중단되지 않습니다).
X86 플랫폼에서 CPU는 교육 실행 중에 버스를 잠그는 수단을 제공합니다. CPU 칩에는 리드 #hlockpin이 있습니다. 접두사 "잠금"이 어셈블리 언어 프로그램의 명령에 추가되면, 어셈블리 머신 코드는 CPU 가이 명령어를 실행할 때 #hlockpin의 잠재력을 낮추고이 명령이 끝날 때까지 해제하여 버스를 잠그게합니다. 이런 식으로, 같은 버스의 다른 CPU는 버스를 통해 메모리에 액세스 할 수 없으므로 다중 프로세서 환경 에서이 명령의 원자력을 보장합니다.
2. java.util.concurrent의 원자 변수
직접이든 간접적이든, java.util.concurrent 패키지의 거의 모든 클래스는 동기화가 아니라 원자 변수를 사용합니다. ConcurrentLinkedqueue와 같은 클래스도 원자 변수를 사용하여 대기 무료 알고리즘을 직접 구현하는 반면 ConsurenThashMap과 같은 클래스는 ReentrantLock을 사용하여 필요할 때 잠그십시오. 그런 다음 ReintrantLock은 원자 변수를 사용하여 스레드 큐를 유지하기 위해 대기합니다.
JDK5.0의 JVM 개선이 없으면이 클래스가 구성되지 않으며,이 클래스는 하드웨어 수준의 동기화 프리미티브에 액세스하기 위해 (사용자 클래스가 아닌 클래스 라이브러리에) 인터페이스를 노출시킵니다. java.util.concurrent의 원자 변수 클래스 및 기타 클래스는 이러한 기능을 사용자 클래스에 노출시킵니다.
java.util.concurrent. 아토마의 원자 클래스
이 패키지는 원자 클래스 세트를 제공합니다. 기본 기능은 다중 스레드 환경에서 여러 스레드가 이러한 클래스의 경우에 포함 된 메소드를 동시에 실행할 때, 스레드가 메소드에 들어가서 지침을 실행할 때 다른 스레드에 의해 방해되지 않으며 다른 스레드는 스핀 잠금 장치와 같다는 것입니다. 메소드가 실행될 때까지 JVM은 대기 대기열에서 다른 스레드를 선택합니다. 이것은 단지 논리적 이해 일뿐입니다. 실제로 관련 하드웨어 지침의 도움으로 구현되며 스레드를 차단하지 않습니다 (또는 하드웨어 수준에서 차단됩니다). 수업은 4 개의 그룹으로 나눌 수 있습니다
Atomicboolean, Atomicinteger, Atomiclong, Atomicreference
atomicintegerarray, atomiclongarray
Atomiclongfieldupdater, Atomicintegerfieldupdater, Atomicreferencefieldupdater
AtomicmarkableReference, AtomicStampedReference, AtomicreferenceArray
그중에서도 Atomicboolean, Atomicinteger, Atomiclong, Atomicreference는 비슷합니다.
우선, Atomicboolean, Atomicinteger, Atomiclong, Atomicreference 내부 API는 비슷합니다. Atomicreference의 예를 들어보십시오.
Atomicreference가있는 스레드 안전 스택을 만듭니다
공개 클래스 LinkedStack <t> {private atomicreference <node <t >> stacks = new atomicreference <node <t >> (); public t push (t e) {node <t> OldNode, newNode; (true) {// 여기의 처리는 매우 특별하므로 그렇습니다. OldNode = stacks.get (); newnode = new Node <t> (e, OldNode); if (stacks.compareAndset (OldNode, NewNode)) {return e;}}} public t pop () {node <t> OldNode, newnode; while (true) {OldNode = stacks.get (); (stacks.compareAndset (OldNode, NewNode)) {return OldNode.Object;}}} 개인 정적 최종 클래스 노드 <T> {private t 객체; private node <T> next; private node (t 객체, node <t> next) {this.Object = 객체; this.next = next;}}}}}}}}}}그런 다음 필드의 원자 업데이트에 집중하십시오.
atomicintegerfieldupdater <t>/atomiclongfieldupdater <t>/atomicreferencefieldupdater <t, v>는 반사에 기초한 필드의 값입니다.
해당 API도 매우 간단하지만 몇 가지 제약 조건도 있습니다.
(1) 필드는 유형의 휘발성이어야합니다! 휘발성이란 무엇입니까? " Java의 휘발성 키워드에 대한 자세한 설명 " 을 확인하십시오.
(2) 필드의 설명 유형 (수정 자 Public/Protected/Default/Private)은 발신자와 작동 객체 필드 간의 관계와 일치합니다. 즉, 발신자는 객체 필드를 직접 작동시킨 다음 원자 작업을 반영하고 수행 할 수 있습니다. 그러나 부모 클래스의 필드의 경우 서브 클래스가 부모 클래스의 필드에 액세스 할 수 있지만 서브 클래스는 직접 작동 할 수 없습니다.
(3) 클래스 변수가 아닌 인스턴스 변수 일 수 있습니다. 즉, 정적 키워드를 추가 할 수 없습니다.
(4) 변수 만 수정할 수 있으며 최종 의미의 의미가 변하지 않기 때문에 최종 변수로 만들 수 없습니다. 실제로, 최종 및 변동성 갈등의 의미 와이 두 키워드는 동시에 존재할 수 없습니다.
(5) Atomicintegerfieldupdater 및 Atomiclongfieldupdater의 경우 int/long 유형의 필드 만 수정할 수 있으며 래퍼 유형 (Integer/Long)을 수정할 수 없습니다. 랩핑 유형을 수정하려면 AtomicreferenceFieldUpdater를 사용해야합니다.
작업 방법은 다음 예제에 설명되어 있습니다.
import java.util.concurrent.atomic.atomicintegerfieldupdater; public class atomicintegerfieldupdaterdemo {class demodata {public volatile value1 = 1; 휘발성 int value2 = 2; 보호 된 휘발성 value3 = 3; 개인 휘발성 4 = 4; atomicinteger fieldupdater <atomicinteger fieldupdater < {return atomicintegerfieldupdater.newupdater (demodata.class, fieldname);} void doit () {demodata data = new demodata (); system.out.println ( "1 ==>"). "+getUpdater ("value2 "). icrementandget (data)); system.out.println ("2 ==> "+getUpdater ("value3 "). retementandget (data)); System.out.println ("true ==> "+getupdater ("value4 "). public static void main ();} {atomicintegerfieldupdaterdemo demo = new atomicintegerfieldupdaterdemo (); demo.doit ();}}위의 예에서, Demodata의 필드 값 3/value4는 Atomicintegerfieldupdaterdemo 클래스에 보이지 않으므로 반사를 통해 그 값을 직접 수정할 수 없습니다.
AtomicmarkableReference 클래스에 의해 설명 된 <오브젝트, 부울> 쌍은 물체 또는 부울의 값을 원자 적으로 수정할 수 있습니다. 이 데이터 구조는 일부 캐시 또는 상태 설명에서 더 유용합니다. 이 구조는 객체/부울을 개별적으로 또는 동시에 수정할 때 효과적으로 처리량을 향상시킬 수 있습니다.
AtomicStampedReference 클래스는 정수 "플래그"로 객체 참조를 유지하고 원자 적으로 업데이트 할 수 있습니다. AtomicmarkableReference 클래스의 <오브젝트, 부울>과 비교하여 AtomicStampedReference는 <객체, int>와 유사한 데이터 구조를 유지합니다. 그러나 atomicinteger와 달리이 데이터 구조는 객체 참조를 전달할 수 있으며이 객체에서 원자 연산을 수행하고 동시에 계산할 수 있습니다.
이 기사의 끝에서 "ABA 문제"는 언급 될 것이며 AtomicMarkAbleReference/AtomicStampedReference는 "ABA 문제"를 해결하는 데 유용합니다.
III. 원자의 역할
이를 통해 단일 데이터의 작동이 원자화 될 수 있습니다.
원자 클래스를 사용하여 복잡한 차단이없는 코드를 구축하십시오
2 개 이상의 원자 변수에 액세스하거나 단일 원자 변수에서 2 개 이상의 작업을 수행하는 것은 일반적으로 동기화가 필요한 것으로 간주되어 이러한 작업이 원자 단위로 사용될 수 있습니다.
잠금 및 대기 알고리즘이 없습니다
CAS (CompareAndswap)를 기반으로 한 동시성 알고리즘을 잠금 알고리즘이라고합니다. 스레드는 더 이상 잠금을 기다릴 필요가 없기 때문입니다 (때로는 스레드 플랫폼의 용어에 따라 Mutxes 또는 중요 부품이라고 함). CAS 작업이 성공하거나 실패하는지 여부는 예측 가능한 시간 내에 완료됩니다. CAS가 실패하면 발신자는 CAS 작업을 재 시도하거나 다른 적절한 작업을 수행 할 수 있습니다.
다른 스레드가 다른 스레드가 지연되거나 실패 할 때 각 스레드가 계속 작동하면 알고리즘에 대기 중이라고 말할 수 있습니다. 대조적으로, Lock-free 알고리즘은 특정 스레드 만 항상 작업을 수행해야합니다. (다른 스레드의 또 다른 정의는 다른 스레드의 작업, 타이밍, 크로스 오버 또는 속도에 관계없이 제한된 단계에서 자체 작업을 올바르게 계산하도록하는 것입니다.이 한계는 시스템의 스레드 수의 수의 함수 일 수 있습니다. 예를 들어, 10 개의 스레드가 Cascounter.increment () 작업을 수행 할 수 있습니다.
지난 15 년 동안 사람들은 대기 및 잠금이없는 알고리즘 (비 블로킹 알고리즘이라고도 함)에 대한 광범위한 연구를 수행했으며 많은 사람들이 일반 데이터 구조에서 비 블로킹 알고리즘을 발견했습니다. 비 블로킹 알고리즘은 운영 체제 및 JVM 레벨에서 널리 사용되며 스레딩 및 프로세스 스케줄링과 같은 작업을 수행합니다. 그들의 구현은 더 복잡하지만 잠금 기반 대체 알고리즘에 비해 많은 장점이 있습니다. 우선 순위 역전 및 교착 상태와 같은 위험을 피할 수 있으며, 경쟁은 저렴하며, 조정은 더 미세한 입상 수준에서 발생하여 더 높은 수준의 평행주의 등을 허용합니다.
흔한:
비 블로킹 카운터
비 블로킹 스택 동의 스택
비 차단 연결 링크 목록 동시 린드 큐
ABA 질문 :
V를 변경하기 전에 CAS는 주로 "V의 값이 여전히 A인지"를 묻고 V에서 V에서 V에서 CAS 작업을 수행하기 전에 A에서 B로 변경 한 다음 A로 다시 CAS 기반 알고리즘을 혼동합니다. 이 경우 CAS 작업이 성공하지만 경우에 따라 결과가 예상 한 것이 아닐 수도 있습니다. 이 유형의 문제를 ABA 문제라고하며, 일반적으로 CAS 작업에서 수행 할 각 값과 태그 또는 버전 번호를 연결하고 값 및 태그를 원자 적으로 업데이트하여 처리합니다. AtomicStampedReference 클래스는이 방법을 지원합니다.
요약
위의 내용은 Java 다중 스레드 원자 패키지에서 원자 변수 및 원자 클래스 작동에 대한이 기사의 모든 자세한 설명입니다. 모든 사람에게 도움이되기를 바랍니다. 관심있는 친구들은이 사이트를 계속 참조 할 수 있습니다.
Java 프로그래밍 : 스레드 간의 멀티 스레드 교착 및 통신은 간단한 코드입니다.
Java 멀티 스레드 프로그래밍 작은 예제는 주차장 시스템을 시뮬레이션합니다
Java Multithreading의 장점 및 코드 예에 대한 간단한 토론
단점이 있으면 메시지를 남겨 두십시오.