동시성 싱글톤 모드에 대한 자세한 소개(코드 포함)
이 글은 동시성(코드 포함)의 싱글톤 모드에 대해 자세히 소개합니다. 필요한 친구들이 참고할 수 있기를 바랍니다.
가장 많은 메모리를 소비하는 객체 생성 프로세스를 제한해야 합니다. 싱글톤 모드(Singleton)는 애플리케이션에서 특정 인스턴스의 인스턴스를 항상 하나만 유지하므로 프로그램 성능을 크게 향상시킬 수 있습니다.
다음에서는 싱글톤의 네 가지 구현 방법에 대해 설명합니다.
单线程下的Singleton的稳定性是极好的,可分为两大类:
1. Eager(eager 유형): 클래스가 로드되는 즉시 객체를 생성합니다.
public class EagerSingleton { //1. 类加载时就立即产生实例对象,通过设置静态变量被外界获取 //2. 并使用private保证封装安全性 private static EagerSingleton eagerSingleton = new EagerSingleton(); //3. 通过构造方法的私有化,不允许外部直接创建对象,确保单例的安全性 private EagerSingleton(){ } public static EagerSingleton getEagerSingleton(){ return eagerSingleton; }
2. Lazy(lazy 유형): 클래스가 로드될 때 개체가 즉시 생성되지 않으며 첫 번째 사용자가 개체를 얻을 때까지 인스턴스화되지 않습니다.
public class LazySingleton { //1. 类加载时并没有创建唯一实例 private static LazySingleton lazySingleton; private LazySingleton() { } //2、提供一个获取实例的静态方法 public static LazySingleton getLazySingleton() { if (lazySingleton == null) { lazySingleton = new LazySingleton(); } return lazySingleton; }
성능 측면에서 보면 LazySingleton이 EagerSingleton보다 확실히 더 좋습니다. 클래스를 로드하는 데 많은 리소스가 필요한 경우(예: 대용량 파일 정보 읽기) LazySingleton의 장점은 분명합니다. 하지만 코드를 읽어보면 치명적인 문제를 쉽게 발견할 수 있습니다. 여러 스레드 간에 보안을 유지하는 방법은 무엇입니까?
멀티 스레드 동시성 문제는 아래에서 분석됩니다.
이 문제를 해결하는 열쇠는 두 가지 측면에 있습니다. 1. 동기화 2. 성능
1. : 동기화 예외는 왜 발생하나요? 설명으로 전형적인 예를 들어보겠습니다.
스레드 A가 있고 스레드 B가 인스턴스를 얻기 위해 동시에 getLazySingleton()을 호출하면 A가 이를 준비할 때 인스턴스가 null이라고 판단합니다. 초기화 중 갑자기 A 스레드가 일시 중단되었습니다. 이때 개체 인스턴스화에 실패했으며 다음으로 더 나쁜 일이 발생했습니다. 스레드 B도 이때 인스턴스가 null이라고 판단했습니다. 인스턴스화 단계에서는 두 개의 인스턴스가 생성되어 원칙적으로 싱글톤이 파괴됩니다.
구출 방법?
Java 개발자라면 synchronized에 익숙할 텐데요. 멀티스레딩하면 대부분의 사람들이 그를 떠올립니다(JDK6 이후에는 성능이 엄청나게 향상되었으며 단순 동시성 문제를 해결하는 데 매우 적합합니다).
그럼 동기화를 사용하여 해결해 보겠습니다.
//由synchronized进行同步加锁 public synchronized static LazySingleton getLazySingleton() { if (lazySingleton == null) { lazySingleton = new LazySingleton(); } return lazySingleton; }
동기화 문제는 해결된 것 같지만 개발자로서 가장 중요한 것은 성능 보장입니다. 잠금 작업에 대한 코드 세그먼트는 비관적으로 잠겨 있으며 하나의 요청이 완료된 후에만 다음 요청을 실행할 수 있습니다. 일반적으로 동기화된 키워드가 포함된 코드 조각은 동일한 규모의 코드보다 몇 배 느릴 수 있는데, 이는 우리가 보고 싶지 않은 것입니다. 그렇다면 이 문제를 피하는 방법은 무엇입니까? Java의 동기화 정의에는 다음 제안이 있습니다. 나중에 동기화를 사용할수록 성능이 향상됩니다(세련된 잠금).
###### 2. 따라서 성능 문제 해결을 시작해야 합니다. 동기화에 따라 최적화: ######
public class DoubleCheckLockSingleton { //使用volatile保证每次取值不是从缓存中取,而是从真正对应的内存地址中取.(下文解释) private static volatile DoubleCheckLockSingleton doubleCheckLockSingleton; private DoubleCheckLockSingleton(){ } public static DoubleCheckLockSingleton getDoubleCheckLockSingleton(){ //配置双重检查锁(下文解释) if(doubleCheckLockSingleton == null){ synchronized (DoubleCheckLockSingleton.class) { if(doubleCheckLockSingleton == null){ doubleCheckLockSingleton = new DoubleCheckLockSingleton(); } } } return doubleCheckLockSingleton; } }
위의 소스 코드는 고전적인 휘발성 키워드(JDK1.5 이후 재탄생) + 이중 검사 잠금(DoubleCheck)으로, 동기화로 인해 발생하는 성능 오버헤드를 최적화합니다. 최대 규모. Volatile과 DoubleCheck에 대해서는 아래에서 설명하겠습니다.
1.휘발성
은 JDK1.5 이후에 공식적으로 구현되어 사용되었습니다. 이전 버전에서는 특별한 구현 없이 이 키워드만 정의했습니다. 휘발성을 이해하려면 JVM 자체 메모리 관리에 대해 어느 정도 이해해야 합니다.
1.1 무어의 법칙에 따르면 메모리의 읽기 및 쓰기 속도는 CPU를 만족시키지 못하기 때문에 현대 컴퓨터에서는 이 방법을 도입했습니다. CPU에 캐시를 추가하는 메커니즘은 캐시에서 메모리 값을 미리 읽고 이를 캐시에 임시 저장한 후 메모리의 해당 값을 업데이트합니다.
**1.2** JVM은 PC의 접근 방식을 모방하여 자체 **작업 메모리**를 메모리에 분할합니다. 이 부분은 캐시와 동일하게 기능하므로 JVM 작업 효율성이 크게 향상됩니다. 이 접근 방식은 작업 메모리가 다른 메모리와 통신할 때 전송 문제도 발생합니다. 휘발성의 한 가지 기능은 캐시와 메모리 간의 불일치를 피하기 위해 메모리에서 최신 값을 강제로 읽는 것입니다.
1.3 휘발성의 또 다른 기능은 JVM과도 관련이 있습니다. 즉, JVM은 자체 판단을 사용하여 소스 코드의 실행 순서를 재정렬하여 명령 파이프라인의 연속성을 보장하여 최적의 결과를 얻습니다. 실행 계획. 이 접근 방식은 성능을 향상시키지만 DoubleCheck에 예상치 못한 결과가 발생하고 두 스레드가 서로 간섭할 수 있습니다. Volatile은 발생 전 보장(쓰기가 읽기보다 우선)을 제공하므로 개체가 방해받지 않고 안전과 안정성을 보장합니다.
2.DoubleCheck
이것은 현대 프로그래밍의 유산입니다. 동기화된 블록에 들어간 후 객체가 인스턴스화되었으며 다시 판단이 필요하다고 가정합니다.
물론 공식적으로 권장되는 싱글톤 구현 방법도 있습니다.
클래스 구성이 정의에서 이미 원자적이므로 위에서 언급한 문제는 다시 발생하지 않으며 좋은 싱글톤 방법입니다. 구현, 권장됩니다.
아아아아위 내용은 동시성 싱글톤 모드에 대한 자세한 소개(코드 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Java의 난수 생성기 안내. 여기서는 예제를 통해 Java의 함수와 예제를 통해 두 가지 다른 생성기에 대해 설명합니다.

Java의 Weka 가이드. 여기에서는 소개, weka java 사용 방법, 플랫폼 유형 및 장점을 예제와 함께 설명합니다.

자바의 암스트롱 번호 안내 여기에서는 일부 코드와 함께 Java의 Armstrong 번호에 대한 소개를 논의합니다.

Java의 Smith Number 가이드. 여기서는 정의, Java에서 스미스 번호를 확인하는 방법에 대해 논의합니다. 코드 구현의 예.

이 기사에서는 가장 많이 묻는 Java Spring 면접 질문과 자세한 답변을 보관했습니다. 그래야 면접에 합격할 수 있습니다.

Java 8은 스트림 API를 소개하여 데이터 컬렉션을 처리하는 강력하고 표현적인 방법을 제공합니다. 그러나 스트림을 사용할 때 일반적인 질문은 다음과 같은 것입니다. 기존 루프는 조기 중단 또는 반환을 허용하지만 스트림의 Foreach 메소드는이 방법을 직접 지원하지 않습니다. 이 기사는 이유를 설명하고 스트림 처리 시스템에서 조기 종료를 구현하기위한 대체 방법을 탐색합니다. 추가 읽기 : Java Stream API 개선 스트림 foreach를 이해하십시오 Foreach 메소드는 스트림의 각 요소에서 하나의 작업을 수행하는 터미널 작동입니다. 디자인 의도입니다
