변수 와 스 레 드 보안

20389 단어 스 레 드 보안
최근 spring 을 보면 서 spring 이 bean scope 에 대한 관 리 는 struts 2 와 달리 spring Controller 의 기본 값 은 singleton 이 고 struts 2 의 Action 은 prototype 으로 두 프레임 워 크 가 이렇게 디자인 된 이 유 는 다 중 스 레 드 안전 과 관련 이 있다 는 것 을 알 게 되 었 다.쉽게 말 하면 Struts 2 의 매개 변 수 는 클래스 의 속성 에 연결 되 어 있 습 니 다. 스 레 드 안전 을 위해 모든 요청 이 Action 인 스 턴 스 를 만들어 야 하기 때문에 scope 는 prototype 입 니 다.한편, SpringMVC 에서 모든 요청 은 하나의 Controller 인 스 턴 스 를 공유 합 니 다. 매개 변 수 는 Controller 에 연결 되 는 방법 으로 부분 변수 에 해당 하기 때문에 scope 는 singleton 으로 설정 하 는 데 문제 가 없 을 것 입 니 다.
이 를 통 해 변수 유형 과 스 레 드 안전 에 대한 사 고 를 했 고 인터넷 에 있 는 자 료 를 참고 하여 테스트 를 한 결과 ThreadLocal 과 국부 변수 안전 을 제외 하고 정적 과 인 스 턴 스 변 수 는 모두 안전 하지 않다 는 것 을 발견 했다.이제 하나씩 말 해 봐.
우선 정적 변수 (클래스 변수) 를 봅 니 다.
 1 package org.thread;

 2 /**

 3  *        

 4  * @author winkey

 5  *

 6  */

 7 public class StaticVar {

 8 

 9     public static void main(String[] args) {

10         Runnable accumelatora = new Accumulatort();  

11         Thread threada = new Thread(accumelatora, "ThreadA");  

12         Thread threadb = new Thread(accumelatora, "ThreadB");  

13         threada.start();  

14         threadb.start(); 

15     }

16 

17 }

18 

19 class Accumulatort implements Runnable {  

20     //       

21     private static int local = 0;  

22     @SuppressWarnings("unchecked")  

23     public void run() {  

24          //       

25         for (int i = 0; i <= 10; i++) {  

26             local += 1;  

27             try {  

28                 Thread.sleep(500);  

29             } catch (Exception e) {  

30             }  

31             System.out.println(Thread.currentThread().getName() + "-->"  

32                     + local);  

33         }  

34     }  

35 }

실행 후 콘 솔 출력 을 보면 특정한 스 레 드 가 변 수 를 사용 할 때 다른 스 레 드 에 의 해 수정 되 었 음 을 알 수 있 습 니 다. 
정적 변 수 는 정적 저장 방식 이기 때문에 정적 저장 방식 이란 프로그램 이 실행 되 는 동안 고정된 저장 공간 을 분배 하 는 방식 을 말한다.즉, 아무리 많은 스 레 드 가 있어 도 방문 은 하나의 변수 이 고 안전 문 제 는 분명 하 다.
다시 말 하면 인 스 턴 스 변수:
 1 package org.thread;

 2 /**

 3  *  scope=singleton ,        

 4  * @author winkey

 5  *

 6  */

 7 public class InstanceVar {

 8 

 9     public static void main(String[] args) {

10         Runnable accumelatora = new Accumulatort2();  

11         Thread threada = new Thread(accumelatora, "ThreadA");  

12         Thread threadb = new Thread(accumelatora, "ThreadB");  

13         threada.start();  

14         threadb.start();  

15     }

16 

17 }

18 

19 class Accumulatort2 implements Runnable {  

20     //       

21     int locals = 0;  

22     @SuppressWarnings("unchecked")  

23     public void run() {  

24         for (int i = 0; i <= 10; i++) {  

25             locals += 1;  

26             try {  

27                 Thread.sleep(1000);  

28             } catch (Exception e) {  

29             }  

30             System.out.println(Thread.currentThread().getName() + "-->"  

31                     + locals);  

32         }  

33     }  

34 } 

안전 할 것 이 라 고 생각 할 지 모 르 지만, 운행 후 안전 문 제 는 곧 발견 할 것 이다.결 과 는 static 와 같 습 니 다.
인 스 턴 스 변 수 는 대상 인 스 턴 스 의 개인 적 인 것 입 니 다. 자바 가상 컴퓨터 의 더미 에서 분 배 됩 니 다. 시스템 에 이 대상 의 인 스 턴 스 만 존재 한다 면 다 중 스 레 드 환경 에서 정적 변수 처럼 특정한 스 레 드 에 의 해 수 정 된 후에 다른 스 레 드 는 수정 을 모두 볼 수 있 기 때문에 스 레 드 가 안전 하지 않 습 니 다.모든 스 레 드 가 서로 다른 대상 에서 실 행 될 경우 대상 과 대상 간 의 인 스 턴 스 변수의 수정 은 서로 영향 을 주지 않 기 때문에 스 레 드 가 안전 합 니 다. 위 에서 우 리 는 두 개의 라인 이지 만 대상 은 하나 이기 때문에 네가 생각 하 는 안전 이 아니다.
부분 변수:
 1 package org.thread;

 2 /**

 3  *       

 4  * @author winkey

 5  *

 6  */

 7 public class LocalVar {

 8 

 9     public static void main(String[] args) {

10         Runnable accumelatora = new Accumulatort3();

11         Thread threada = new Thread(accumelatora, "ThreadA");

12         Thread threadb = new Thread(accumelatora, "ThreadB");

13         threada.start();

14         threadb.start();

15     }

16 

17 }

18 

19 class Accumulatort3 implements Runnable {

20     @SuppressWarnings("unchecked")

21     public void run() {

22         //     

23         int locals = 0;

24         for (int i = 0; i <= 10; i++) {

25             locals += 1;

26             try {

27                 Thread.sleep(1000);

28             } catch (Exception e) {

29             }

30             System.out.println(Thread.currentThread().getName() + "-->"

31                     + locals);

32         }

33     }

34 }

안 되면 몇 번 더 운행 해. 괜찮아, 스 레 드 안전 해.
모든 스 레 드 가 실 행 될 때 부분 변 수 를 각 스 택 프레임 의 작업 메모리 에 두 고 스 레 드 간 에 공유 되 지 않 기 때문에 안전 문제 가 없습니다.
일반적으로 다 중 스 레 드 프로 그래 밍 을 할 때 가장 생각 나 는 것 은 ThreadLocal 입 니 다.
ThreadLocal 사용 장 소 는 주로 다 중 스 레 드 에서 데이터 데이터 데이터 가 병발 로 인해 일치 하지 않 는 문 제 를 해결 합 니 다.ThreadLocal 은 모든 스 레 드 의 동시 방문 데이터 에 복사 본 을 제공 하고 복사 본 을 방문 하여 업 무 를 수행 합 니 다. 이러한 결 과 는 메모리 가 소모 되 었 고 스 레 드 동기 화가 가 져 온 성능 소 모 를 크게 줄 였 으 며 스 레 드 병행 제어 의 복잡 도 를 줄 였 습 니 다.
이 클래스 는 스 레 드 부분 (thread - local) 변 수 를 제공 합 니 다.이 변 수 는 일반적인 대응 물 과 다 릅 니 다. 변 수 를 방문 하기 때 문 입 니 다. get 혹시 set 방법) 모든 스 레 드 는 변수의 초기 화 복사 본 에 독립 된 부분 변 수 를 가지 고 있 습 니 다.ThreadLocal 인 스 턴 스 는 보통 클래스 의 private static 필드 입 니 다. 상 태 를 특정한 스 레 드 (예 를 들 어 사용자 ID 나 트 랜 잭 션 ID) 와 연결 하 기 를 원 합 니 다.
 1 package org.thread;

 2 

 3 public class ThreadLocalVar {

 4     //         

 5     @SuppressWarnings("unchecked")  

 6     public static ThreadLocal threadLocal = new ThreadLocal();  

 7   

 8     public static void main(String[] args) {  

 9         Runnable accumelatora = new Accumulatort4();  

10         Thread threada = new Thread(accumelatora, "ThreadA");  

11         Thread threadb = new Thread(accumelatora, "ThreadB");  

12         threada.start();  

13         threadb.start();  

14     } 

15 

16 }

17 

18 class Accumulatort4 implements Runnable {  

19     @SuppressWarnings("unchecked")  

20     public void run() {  

21         //         

22         ThreadLocal threadLocal = ThreadLocalVar.threadLocal;  

23         for (int i = 1; i <= 10; i++) {  

24             if (threadLocal.get() == null)  

25                 threadLocal.set(new Integer(0));  

26             int x = ((Integer) threadLocal.get()).intValue();  

27             x += 1;  

28             threadLocal.set(new Integer(x));  

29             try {  

30                 Thread.sleep(1000);  

31             } catch (InterruptedException e) {  

32             }  

33             System.out.println(Thread.currentThread().getName() + "-->"  

34                     + ((Integer) threadLocal.get()).intValue());  

35         }  

36     }  

37 }  

위의 코드 는 사실 모든 라인 에 자신의 변수 복사 본 이 있 기 때문에 안전 에 문제 가 없 을 것 이다. 
그것 과 synchronized 의 차 이 는 모두 스 레 드 안전 을 위 한 것 이지 만 본질 적 인 차이 이다.
synchronized 는 잠 금 체 제 를 이용 하여 변수 나 코드 블록 을 한 스 레 드 에 만 접근 할 수 있 도록 합 니 다.한편, ThreadLocal 은 모든 스 레 드 에 변수의 복사 본 을 제공 하여 모든 스 레 드 가 특정한 시간 에 같은 대상 이 아니 라 여러 스 레 드 가 데이터 에 대한 데이터 공 유 를 격 리 시 켰 다.반면 Synchronized 는 반대로 여러 스 레 드 간 통신 시 데이터 공 유 를 얻 을 수 있 습 니 다.Synchronized 는 스 레 드 간 데이터 공유 에 사용 되 고 ThreadLocal 은 스 레 드 간 데이터 격 리 에 사 용 됩 니 다.물론 ThreadLocal 은 synchronized 를 대체 할 수 없습니다. 서로 다른 문제 영역 을 처리 합 니 다.synchronized 는 다 중 스 레 드 환경 에서 의 데이터 동기 화 를 처리 하 는 데 사용 되 며, ThreadLocal 은 현재 스 레 드 의 개인 적 인 상 태 를 저장 하기 위 한 것 입 니 다.

좋은 웹페이지 즐겨찾기