java에서 ThreadLocal 로컬 스레드와 동기화 메커니즘 비교

ThreadLocal 디자인
우선 ThreadLocal의 인터페이스를 살펴보겠습니다.

Object get() ; //   protected Object
initialValue(); //            
void set(Object value); //  
ThreadLocal에는 세 가지 방법이 있는데 그 중에서 주의해야 할 것은 initial Value () 이다. 이 방법은 보호된 방법으로 하위 클래스를 다시 쓰기 위해 일부러 이루어진 것이 분명하다.이 방법은 현재 스레드가 이 스레드 국부 변수의 초기 값을 되돌려줍니다. 이 방법은 지연 호출 방법입니다. 한 스레드가 get () 또는 set (Object) 를 처음 호출할 때만 실행되고 1회만 실행됩니다.ThreadLocal에서 null을 직접 반환합니다.
protected Object initialValue() { return null; }
ThreadLocal은 각 스레드를 위해 변수의 복사본을 어떻게 유지합니까?사실 실현된 사고방식은 매우 간단하다. ThreadLocal 클래스에 맵이 하나 있는데 각 라인의 변수를 저장하는 데 사용되는 복사본이다.
예를 들어 다음 예시 구현: 맵 저장에 해당합니다. 이것은ThreadLocal의 get 방법의 실현입니다.
 

public T get() {
    Thread t = Thread.currentThread();// 
    ThreadLocalMap map = getMap(t);
    if (map != null) {
      ThreadLocalMap.Entry e = map.getEntry(this);
      if (e != null)
        return (T)e.value;
    }
    return setInitialValue();
  }
  
  
   ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
  }
ThreadLocal 및 기타 동기화 메커니즘 비교
ThreadLocal은 다른 동기화 메커니즘에 비해 어떤 장점이 있습니까?ThreadLocal과 기타 모든 동기화 메커니즘은 다중 노드에서 같은 변수에 대한 접근 충돌을 해결하기 위해 일반적인 동기화 메커니즘에서는 대상에 자물쇠를 채워 여러 노드가 같은 변수에 대한 안전한 접근을 실현한다.이때 이 변수는 여러 개의 스레드가 공유된다. 이런 동기화 메커니즘을 사용하면 언제 변수를 읽고 쓰는지, 언제 특정한 대상을 잠가야 하는지, 언제 이 대상의 자물쇠를 놓아야 하는지 등 세밀하게 분석해야 한다.이 모든 것은 여러 개의 라인이 자원을 공유했기 때문이다.ThreadLocal은 또 다른 측면에서 다중 스레드의 병렬 접근을 해결한다. ThreadLocal은 모든 스레드에 이 스레드와 연결된 변수의 복사본을 유지하고 여러 스레드의 데이터를 격리한다. 모든 스레드는 자신의 변수 복사본을 가지고 있기 때문에 이 변수를 동기화할 필요가 없다.ThreadLocal은 다중 스레드 코드를 작성할 때 안전하지 않은 전체 변수를 ThreadLocal에 봉인하거나 이 대상의 특정한 스레드 상태를 ThreadLocal에 봉인할 수 있는 안전한 공유 대상을 제공합니다.
ThreadLocal에서 모든 종류의 대상을 보유할 수 있기 때문에, ThreadLocal get의 현재 라인을 사용하는 값은 강제 형식 변환이 필요합니다.그러나 새로운 자바 버전 (1.5) 이 모듈을 도입함에 따라 새로운 모듈 파라미터를 지원하는 ThreadLocal류가 이득을 보게 될 것이다.강제 형식 변환을 줄이고 일부 오류 검사를 컴파일러로 앞당겨 ThreadLocal의 사용을 어느 정도 간소화할 수 있습니다.
총결산
물론 ThreadLocal은 동기화 메커니즘을 대체할 수 없으며, 양자 지향의 문제 영역은 다르다.동기화 메커니즘은 여러 개의 스레드가 같은 자원에 대한 병렬 접근을 동기화하기 위한 것이고 여러 개의 스레드 간에 통신을 하는 효과적인 방식이다.ThreadLocal은 여러 개의 라인을 격리하는 데이터 공유로 근본적으로 여러 개의 라인 사이에 자원(변수)을 공유하지 않기 때문에 여러 개의 라인을 동기화할 필요가 없다.따라서 만약에 여러 개의 스레드 간에 통신을 해야 한다면 동기화 메커니즘을 사용한다.여러 스레드 간의 공유 충돌을 격리해야 한다면, ThreadLocal을 사용하면 프로그램을 매우 간소화하고 프로그램을 더욱 읽기 쉽고 간결하게 할 수 있습니다.
ThreadLocal의 일반적인 용도:
현재 세션 사용자 저장
웹 워크의 ActionContext 같은 context 변수를 저장합니다.
Spring hibernate orm의 세션을 저장합니다.
예: ThreadLocal로 각 스레드 Singleton 구현
스레드 국부 변수는 상태'단자'(Singleton)나 스레드가 안전한 공유 대상을 묘사하거나 안전하지 않은 전체 변수를 ThreadLocal에 봉인하거나 대상의 특정한 스레드에 대한 상태를 ThreadLocal에 봉인하는 데 자주 사용된다.예를 들어 데이터베이스와 밀접한 관계를 가진 응용 프로그램에서 프로그램의 많은 방법이 데이터베이스에 접근해야 할 수 있다.시스템의 모든 방법에 하나의 연결을 매개 변수로 포함하는 것은 불편하다.'단자'로 연결에 접근하는 것은 더욱 거칠지만 훨씬 편리한 기술일 수 있다.그러나 여러 스레드는 JDBC Connection을 안전하게 공유할 수 없습니다.명세서 3에서 보듯이, "단서"의ThreadLocal을 사용하면 프로그램의 모든 종류에서 모든 스레드 연결에 대한 인용을 쉽게 얻을 수 있습니다.이렇게 하면 ThreadLocal이 각 스레드 목록을 만들 수 있다고 생각할 수 있습니다.

package org.heinrich.app.connection;

import java.sql.Connection;

public class ConnectionUtils {
 
 
 private final static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
 
 
 public Connection getConnection(){
 Connection connection = threadLocal.get();
 if(connection ==null){
  connection = new DBHelper().getConn();
  threadLocal.set(connection);
 }
 
 return connection;
 }
 
 

}

package org.heinrich.app.connection;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
// 
public class DBHelper {
 public static final String url = "jdbc:mysql://localhost:3306/fk_test";
 public static final String name = "com.mysql.jdbc.Driver";
 public static final String user = "root";
 public static final String password = "root";

 public Connection conn = null;

 public Connection getConn() {
 try {
  Class.forName(name);//  
  conn = DriverManager.getConnection(url, user, password);//  
 } catch (Exception e) {
  e.printStackTrace();
 }
 return conn;
 }

}

Mysql 연결 루트의 안전을 간단하게 실현하는 방식
이론적으로 말하자면 ThreadLocal은 확실히 모든 라인에 비해 모든 라인에는 자신의 ThreadLocal이 있다.그러나 일반적인 응용 서버는 스레드 탱크를 유지한다고 위에서 말했다.따라서 서로 다른 사용자가 접근하면 같은 라인을 받아들일 수 있다.따라서 TheadLocal 기반 작업을 할 때ThreadLocal 변수의 캐시가 발생하지 않도록 조심해야 하며, 다른 루트가 이 루트 변수에 접근하도록 해야 한다.
읽어주셔서 감사합니다. 여러분에게 도움이 되었으면 좋겠습니다. 본 사이트에 대한 지지에 감사드립니다!

좋은 웹페이지 즐겨찾기