HashMap을 스레드로부터 안전하게 사용하기 위한 네 가지 기술

이 기사에서는 HashMap을 스레드로부터 안전하게 사용하는 네 가지 기술에 대해 설명합니다.

내부 메소드 1개: 스레드당 별도의 HashMap 사용

아래 그림과 같이 Tomcat은 요청을 받은 후 컨트롤러, 서비스 계층 서비스, 데이터베이스 액세스 계층의 관련 메서드를 차례로 호출합니다.

서비스 계층 메소드인 serviceMethod에 접근할 때마다 메소드 본문 내부에 별도의 HashMap이 생성되고, 관련 요청 매개변수가 HashMap에 복사된 후 DAO 메소드가 호출되어 데이터베이스 작업을 수행하게 됩니다.

각 HTTP 처리 스레드는 서비스 계층 메서드 본문 내부에 자체 인스턴스를 가지고 있습니다 . 다중 스레드 환경에서는 동기화 작업을 수행 HashMap할 필요가 없습니다 .HashMap

이는 우리가 사용하는 가장 일반적이고 안전한 방법이기도 하며, CRUD의 가장 기본적인 작업이기도 합니다.

2 구성 데이터: 초기 쓰기, 후속 읽기만

시스템이 시작된 후 구성 정보를 로컬 캐시 HashMap에 로드할 수 있습니다. 구성 정보가 초기화된 후에는 이를 쓸 필요가 없으며 향후에는 읽기 작업만 제공됩니다.

위 그림은 내부에 HashMap 개체 configMap이 있는 매우 간단한 구성 클래스 SimpleConfig를 보여줍니다. 생성자는 초기화 메서드를 호출하고 초기화 메서드의 내부 논리는 구성 데이터를 HashMap에 저장하는 것입니다.

SimpleConfig 클래스는 getConfig 메서드를 외부 세계에 노출합니다. 기본 스레드가 SimpleConfig 개체를 초기화한 후 다른 스레드가 getConfig 메서드를 호출하면 읽기 작업만 있고 쓰기 작업이 없으므로 스레드로부터 안전합니다.

3 읽기-쓰기 잠금: 쓰기 시 차단, 병렬 읽기, 더 많이 읽고 더 적게 쓰기 시나리오

읽기-쓰기 잠금은 읽기 잠금과 쓰기 잠금의 두 부분으로 나누어진 잠금입니다. 읽기 잠금은 여러 스레드가 동시에 잠금을 획득할 수 있도록 하는 반면, 쓰기 잠금은 상호 배제 잠금입니다.

규칙은 다음과 같습니다.<strong style="font-size: 상속;line-height: 상속;color: rgb(255, 104, 39);">읽기와 읽기는 상호 배타적이지 않으며, 읽기와 쓰기는 상호 배타적입니다. 쓰기와 쓰기는 상호 배타적이며 </strong> 읽기는 많고 쓰기는 적은 비즈니스 시나리오에 적합합니다.

우리는 일반적으로 ReadWriteLock을 구현하는 ReentrantReadWriteLock을 사용합니다. ReadWriteLock 인터페이스도 매우 간단합니다. 주로 내부적으로 읽기 잠금과 쓰기 잠금을 각각 반환하는 두 가지 메서드를 제공합니다.

 public interface ReadWriteLock {
    //获取读锁
    Lock readLock();
    //获取写锁
    Lock writeLock();
}

읽기-쓰기 잠금의 사용은 다음과 같습니다.

  1. ReentrantReadWriteLock 객체를 생성합니다. ReadWriteLock을 사용할 때 직접 사용되지는 않지만 내부 읽기 잠금 및 쓰기 잠금을 얻은 다음 각각 잠금/잠금 해제 메서드를 호출합니다.
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
  1. 공유 데이터를 읽습니다.
Lock readLock = readWriteLock.readLock();
readLock.lock();
try {
   // TODO 查询共享数据
} finally {
   readLock.unlock();
}
  1. 공유 데이터 쓰기
Lock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
   // TODO 修改共享数据
} finally {
   writeLock.unlock();
}

다음 코드는 ReadWriteLock을 사용하여 HashMap을 스레드로부터 안전하게 사용하는 방법을 보여줍니다.

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockCache {
  
    // 创建一个 HashMap 来存储缓存的数据
    private Map<String, String> map = new HashMap<>();

    // 创建读写锁对象
    private ReadWriteLock rw = new ReentrantReadWriteLock();

    // 放对象方法:向缓存中添加一个键值对
    public void put(String key, String value) {
        // 获取写锁,以确保当前操作是独占的
        rw.writeLock().lock();
        try {
            // 执行写操作,将键值对放入 map
            map.put(key, value);
        } finally {
            // 释放写锁
            rw.writeLock().unlock();
        }
    }

    // 取对象方法:从缓存中获取一个值
    public String get(String key) {
        // 获取读锁,允许并发读操作
        rw.readLock().lock();
        try {
            // 执行读操作,从 map 中获取值
            return map.get(key);
        } finally {
            // 释放读锁
            rw.readLock().unlock();
        }
    }
}

읽기-쓰기 잠금을 사용하여 HashMap을 작동하는 것은 매우 고전적인 기술입니다. 메시지 미들웨어 RockeMQ NameServer(이름 서비스)는 이 기술을 통해 라우팅 정보를 저장하고 쿼리합니다.

또한 읽기-쓰기 잠금은 여러 HashMap을 작동할 수 있습니다. ConcurrentHashMap과 비교하여 ReadWriteLock은 캐시 개체의 세분성을 제어할 수 있으며 유연성이 뛰어납니다.

4 Collections.synchronizedMap: 읽기 및 쓰기 모두에 대해 잠김

다음 코드는 여러 스레드에서 userMap을 사용할 때,

static Map<Long, User> userMap = Collections.synchronizedMap(new HashMap<Long, User>());

동기화된 맵 메소드를 입력하십시오:

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
       return new SynchronizedMap<>(m);
}

내부적으로는 HashMap의 읽기 및 쓰기 작업을 다시 구현하는 래퍼 클래스인 개체 잠금 개체 뮤텍스가 포함되어 있습니다. 이를 읽거나 쓸 때마다 동기화 키워드가 스레드 안전성을 보장하는 데 사용됩니다. 작업.

Collections.synchronizedMap 기술은 사용하기가 매우 간단하지만 읽고 쓸 때마다 잠기고 성능이 특별히 좋지 않다는 점을 이해해야 합니다.

5 요약

이 기사에서 저자는 HashMap을 사용하기 위한 네 가지 스레드 안전 기술을 요약합니다.

1. 메소드 내부: 각 스레드는 별도의 HashMap을 사용합니다.

이것은 가장 일반적으로 사용되며 매우 신뢰할 수 있는 방법입니다. 각 스레드는 메서드 본문 내부에 인스턴스를 생성합니다 HashMap. 다중 스레드 환경에서는 HashMap동기화 작업이 필요하지 않습니다.

2. 구성 데이터: 최초 쓰기, 후속 읽기만 가능

미들웨어가 시작되면 구성 파일을 읽고 구성 데이터를 HashMap에 씁니다. 메인 스레드가 쓰기를 마친 후에는 더 이상 쓰기 작업이 없으며 다른 스레드는 스레드 안전을 초래하지 않고 이를 읽을 수 있습니다. 문제.

3. 읽기-쓰기 잠금: 쓰기 시 차단, 병렬 읽기, 더 많이 읽고 더 적게 쓰기 시나리오

읽기-쓰기 잠금은 읽기 잠금과 쓰기 잠금의 두 부분으로 나누어진 잠금입니다. 읽기 잠금은 여러 스레드가 동시에 잠금을 획득할 수 있도록 하는 반면, 쓰기 잠금은 상호 배제 잠금입니다.

규칙은 다음과 같습니다.<strong style="font-size: 상속;line-height: 상속;color: rgb(255, 104, 39);">읽기와 읽기는 상호 배타적이지 않으며, 읽기와 쓰기는 상호 배타적입니다. 쓰기와 쓰기는 상호 배타적이며 </strong> 읽기는 많고 쓰기는 적은 비즈니스 시나리오에 적합합니다.

읽기-쓰기 잠금을 사용하여 HashMap을 작동하는 것은 매우 고전적인 기술입니다. 메시지 미들웨어 RockeMQ NameServer(이름 서비스)는 이 기술을 통해 라우팅 정보를 저장하고 쿼리합니다.

4. Collections.synchronizedMap: 읽기 및 쓰기 모두에 대해 잠김

Collections.synchronizedMap 메서드는 데코레이터 패턴을 사용하여 스레드가 안전하지 않은 HashMap에 대한 스레드로부터 안전한 데코레이터 클래스 동기화 맵을 제공합니다.

SynchronizedMap은 HashMap의 작업이 스레드로부터 안전한지 간접적으로 확인하는 데 사용되며,SynchronizedMap의 기본 계층도 작업의 스레드 안전성을 보장하기 위해 동기화된 키워드를 사용합니다.

"Celebrateing More Than Years 2"의 불법 복제 리소스가 npm에 업로드되어 npmmirror가 unpkg 서비스 를 중단해야 했습니다. Microsoft의 중국 AI 팀은 수백 명의 사람들을 모아 미국으로 떠났습니다. 프론트엔드 시각화 라이브러리와 Baidu의 유명한 오픈 소스 프로젝트 ECharts - Fish 사기꾼을 지원하기 위한 "going to the sea"는 TeamViewer를 사용하여 398만 개를 전송했습니다! 원격 데스크톱 공급업체는 무엇을 해야 합니까? Zhou Hongyi: Google은 시간이 얼마 남지 않았습니다. 모든 제품을 오픈소스로 만드는 것이 좋습니다. 한 유명 오픈소스 회사의 전직 직원이 소식을 전했습니다. 부하 직원의 도전을 받은 후 기술 리더는 분노했습니다. Google은 Android 가상 머신에서 ChromeOS를 실행하는 방법을 보여주었습니다. 여기서 time.sleep(6)은 어떤 역할을 합니까? 마이크로소프트, 중국 AI 팀이 "미국을 위해 준비 중"이라는 루머에 대응 사무용 소프트웨어의 마트료시카 같은 충전에 대한 인민일보 온라인 논평: "세트"를 적극적으로 해결해야만 미래를 가질 수 있다
{{o.이름}}
{{이름}}

추천

출처my.oschina.net/makemyownlife/blog/11174967