SlideShare une entreprise Scribd logo
1  sur  18
Télécharger pour lire hors ligne
Appendix-A 동시성 II

     chois79




12년 9월 10일 월요일
Review of Chapter-13 동시성 I
     •   다중 스레드(동시성) 코드는 올바로 구현하기가 어렵다


     •   동시성의 오해


          •   동시성은 항상 성능을 높여준다


          •   동시성을 구현해도 설계는 변하지 않는다


          •   동기화 라이브러리를 사용하면 동시성을 이해할 필요가 없다


     •   동시성 방어 원칙


          •   SRP(단일 책임 원칙): 동시성은 복잡성 하나만으로도 따로 분리할 이유가 충분


          •   공유 데이터의 최소화 및 캡슐화


          •   복사본을 사용


          •   스레드는 가능한한 독립적으로 구현


     •   동시성 구현 코드 테스트


          •   완벽한 증명하기는 현실적으로 불가능


          •   많은 플랫폼에서 많은 구성으로 반복해서 테스트가 필요




12년 9월 10일 월요일
클라이언트/서버 예제(1/4)

     • Non-Thread Version

           ServerSocket serverSocket = new ServerSocket(8009);
           while (keepProcessing) {
           	    try {
           	    	    Socket socket = serverSocket.accept();
           	    	    process(socket);
           	    } catch (Exception e) {
                	    handle(e);
           	    }
           }



          • 만약 성능 이슈가 발생한다면?


     • 응용 프로그램의 수행시간 종류


          • 프로세서 - 수치 계산, 정규 표현식 처리, 가비지 컬렉션


          • I/O - 소켓 사용, 데이터 베이스 연결, 가상 메모리 스와핑 기다리기


                 • 멀티 스레드로 성능 개선 가능




12년 9월 10일 월요일
클라이언트/서버 예제(2/4)

     • Thread Version
            void process(final Socket socket) {
          	     if (socket == null)
          	     	    return;
          	     Runnable clientHandler = new Runnable() {
          	     	    public void run() {
          	     	    	    try {
          	     	    	    	    String message = MessageUtils.getMessage(socket);
          	     	    	    	    MessageUtils.sendMessage(socket, "Processed: " + message);
          	     	    	    	    closeIgnoringException(socket);
          	     	    	    } catch (Exception e) {
          	     	    	    	    e.printStackTrace();
          	     	    	    }
          	     	    }
          	     	
          	     };
          	     Thread clientConnection = new Thread(clientHandler);
          	     clientConnection.start();
          }



          • 이 코드의 문제점


                 • 하나 이상의 책임: 소켓 연결 관리, 클라이언트 처리, 스레드 정책, 서버 종료 정책


                 • 다양한 추상화 수준



12년 9월 10일 월요일
클라이언트/서버 예제(3/4)

     • 책임별로 클래스를 분리


          • ClientConnection: 소켓 연결 관리


          • ClientRequestProcessor: 클라이언트 처리


          • ClientScheduler: 스레드 정책


          • ConnectionManager: 서버 종료 정책

           public void run() {
           	    while (keepProcessing) {
           	    	    try {
           	    	    	    ClientConnection clientConnection = connectionManager.awaitClient();
           	    	    	    ClientRequestProcessor requestProcessor = new ClientRequestProcessor(clientConnection);
           	    	    	    clientScheduler.schedule(requestProcessor);
           	    	    } catch (Exception e) {
           	    	    	    e.printStackTrace();
           	    	    }
           	    }
           	    connectionManager.shutdown();
           }




12년 9월 10일 월요일
클라이언트/서버 예제(4/4)

     • 스레드 정책 코드 및 확장
           public interface ClientScheduler {
           	    public void schedule(ClientRequestProcessor requestProcessor);
           }
           public class ThreadPerRequestScheduler implements ClientScheduler {
           	    @Override
           	    public void schedule(final ClientRequestProcessor requestProcessor) {
           	    	     Runnable runnable = new Runnable() {
           	    	     	    public void run() {
           	    	     	    	     requestProcessor.process();
           	    	     	    }
           	    	     };
           	    	     Thread thread = new Thread(runnable);
           	    	     thread.start();
           	    }
           }



           // Java Executor framework을 사용한 Thread 정책 변경
           public class ExecutorClientScheduler implements ClientScheduler {
           	    Executor executor;
           	    public ExecutorClientScheduler(int availableThreads) {
           	    	     executor = Executors.newFixedThreadPool(availableThreads);
           	    }
           	    public void schedule(final ClientRequestProcessor requestProcessor) {
           	    	     Runnable runnable = new Runnable() {
           	    	     	    public void run() {
           	    	     	    	     requestProcessor.process();
           	    	     	    }
           	    	     };
           	    	     executor.execute(runnable);
           	    }
           }




12년 9월 10일 월요일
가능한 실행 경로(1/2)

     • 2개의 스레드로 이 코드를 실행한다면?

          public class IdGenerator {
          	    int lastIdUsed;

          	      public int incrementValue() {
          	      	    return ++lastIdUsed;
          	      }
          }



          • lastIdUsed의 초기값이 93일 경우


                 • 스레드 1이 94를 얻고, 스레드 2가 95를 얻고, lastIdUsed가 95가 된다


                 • 스레드 1이 95를 얻고, 스레드 2가 94를 얻고, lastIdUsed가 95가 된다


                 • 스레드 1이 94를 얻고, 스레드 2가 94를 얻고, lastIdUsed가 94가 된다


                     • JVM의 구현 방식에 따라 이 결과도 가능



12년 9월 10일 월요일
가능한 실행 경로(2/2)

     • 경로의 수


          • return ++lastIdUsed는 바이트 코드 8개로 구성됨


          • 루프나 분기가 없이 명령 N개를 T개의 스레드로 실행했을때 가능한 경로의 수




                 • Ex) N = 8이고, T = 2이면 가능한 경로의 수: 12,870


          • Synchronized를 적용했을 경우


                 • 가능한 경로의 수: 2(T)

                    public synchronized int incrementValue() {
                    	    return ++lastIdUsed;
                    }




12년 9월 10일 월요일
라이브러리를 이해하라(1/3)

     • Executor 프레임워크


          • 스레드 풀 관리


          • Runnable 인터페이스 지원


          • Callable/Future 인터페이스 지원


                 • 스레드의 수행 결과를 받아오기 위해 사용

                   public String processRequest(String message) throws Exception {
                   	    Callable<String> makeExternalCall = new Callable<String>() {
                   	    	    public String call() throws Exception {
                   	    	    	    String result = "";
                   	    	    	    // make external request
                   	    	    	    return result;
                   	    	    }
                   	    };
                   	    Future<String> result = executorService.submit(makeExternalCall);
                   	    String partialResult = doSomeLocalProcessing();
                   	    return result.get() + partialResult;
                   }




12년 9월 10일 월요일
라이브러리를 이해하라(2/3)
     •   스레드를 중단하지 않는 방법

          •   Synchronized 및 Lock

                 •   비관적 잠금: 항상 락을 사용


                     public class ObjectWithValue {
                     	    private int value;
                     	    public synchronized void incrementValue() { ++value;}
                     	    public int getValue() { return value; }
                     }


          •   AtomicInteger 사용 - Concurrent package

                 •   낙관적 잠금: 현재 변수 값이 최종으로 알려진 값일 경우 갱신하고, 그렇지 않을 경우 성공할때까지 재 시도

                 •   프로세서의 CAS(Compare And Swap) 연산을 사용


                     public class ObjectWithValue {
                     	    private AtomicInteger value = new AtomicInteger();
                     	    public void incrementValue() { value.incrementAndGet(); }
                     	    public int getValue() { return value.get();
                     }




                     // CAS의 구현
                     int variableBeingSet;
                     void simulateNonBlockingSet(int newValue) {
                     	    int currentValue;
                     	    do {
                     	    	    currentValue = variableBeingSet;
                     	    } while (currentValue != compareAndSwap(currentValue, newValue));
                     }


12년 9월 10일 월요일
라이브러리를 이해하라(3/3)

     • 스레드에 안전하지 않은 클래스


          • SimpleDateFormat, java.util 컨테이너 클래스...


          • 해결 방안


                 • 스레드 안전 라이브러리 사용


                 • 직접 구현


                   • 클라이언트 기반 잠금 메커니즘


                     • 공유 데이터를 사용하는 모든 곳에서 lock을 사용


                   • 서버 기반 잠금 메커니즘


                     • 공유 데이터에 접근을 제어하는 별도의 클래스로 랩핑

12년 9월 10일 월요일
메소드 사이에 존재하는 의존성을 조심하라(1/3)

     • 의존성 예제


          • 여러 메소드에서 하나의 변수를 공유해서 사용
                 public class IntegerIterator implements Iterator<Integer> {
                 	    private Integer nextValue = 0;

                 	   public synchronized boolean hasNext() {
                 	   	    return nextValue < 100000;
                 	   }
                 	   public synchronized Integer next() {
                 	   	    if (nextValue == 100000)
                 	   	    	    throw new IteratorPastEndException();
                 	   	    return nextValue++;
                 	   }
                 	   public synchronized Integer getNextValue() {
                 	   	    return nextValue;
                 	   }
                 }




          • 만약 다중 스레드가 IntegerIterator 인스턴스 하나를 공유 한다면?

                 while(iterator.hasNext()) {
                 	    int nextValue = iterator.next();
                 	    // nextValue로 뭔가를 한
                 }                                   오류 발생: nextValue가 100000을 넘을 가능성이 존재


12년 9월 10일 월요일
메소드 사이에 존재하는 의존성을 조심하라(2/3)
     •   해결책


          •   실패를 용인


          •   클라이언트 기반 잠금: 모든 클라이언트에서 동기화 로직 구현


                 •   DRY(Don’t Repeat Yourself) 원칙 위반: 중복으로 인한 오류 발생이 쉬움

                     while (true) {
                     	    int nextValue;
                                                              Client-based
                     	    synchronized (iterator) {
                     	    	    if (!iterator.hasNext())
                     	    	    	    break;
                     	    	    nextValue = iterator.next();
                     	
                     	
                          }
                          doSometingWith(nextValue);
                                                                                                        Server-based
                     }
                                                                           public class IntegerIteratorServerLocked {
                                                                           	    private Integer nextValue = 0;
                                                                           	    public synchronized Integer getNextOrNull() {
          •   서버 기반 잠금
                                                                           	    	    if (nextValue < 100000)
                                                                           	    	    	    return nextValue++;
                 •   코드 중복이 줄어듬: 오류가 발생할 가능성이 줄어듬                          	    	    else
                                                                           	    	    	    return null;
                                                                           	    }
                 •   성능이 좋아짐                                               }

                                                                           while (true) {
                 •   스레드 정책이 하나임
                                                                           	    int nextValue = iterator.getNextOrNull();;
                                                                           	    if (next == null)
                 •   공유 변수가 줄어든다                                           	    	    break;
                                                                           	    doSometingWith(nextValue);
                                                                           }


12년 9월 10일 월요일
메소드 사이에 존재하는 의존성을 조심하라(3/3)

     • 서버 코드에 손대지 못하는 경우


          • Adapter 패턴을 적용

                 public class ThreadSafeIntegerIterator {
                 	    private IntegerIterator iterator = new IntegerIterator();
                 	    public synchronized Integer getNextOrNull() {
                 	    	    if (iterator.hasNext())
                 	    	    	    return iterator.next();
                 	    	    return null;
                 	    }
                 }




12년 9월 10일 월요일
작업 처리량 높이기

     • EX) 네트워크에서 페이지를 읽어 분석하는 프로그램


          • 가정


                 • 페이지를 읽어 오는 평균 I/O 시간: 1초


                 • 페이지를 분석하는 평균 처리시간: 0.5초


                 • 처리는 CPU 100% 사용, I/O는 CPU 0% 사용


          • 단일 스레드 환경


                 • N 페이지를 처리하는 총 실행시간: 1.5초 * N


          • 멀티 스레드 환경


                 • 3개의 스레드로 동시에 실행한다면?


                    • I/O 1초동안 다른 2개의 스레드는 페이지를 분석할 수 있어 단일 스레드에 비해 약 3배의 처리 속도를 가짐




12년 9월 10일 월요일
데드락(1/2)

     • 4가지 조건을 모두 만족하는 경우 데드락 발생


          • 상호배제(Mutual exclusion)
                                                       use
                                    Thread#1

                                                                Res1

                                    Thread#2
                                                      not use

          • 잠금&대기(Lock&Wait)                           use
                                    Thread#1

                                                                Res1

                                    Thread#2
                                                       wait


          • 선점불가(No Preemption)
                                                       use
                                    Thread#1

                                                                Res1

                                    Thread#2
                                                 not preemptive

          • 순환대기(Circular Wait)
                                    lock       Res1             request


                                                                  Thread#2
                             Thread#1

                                  request      Res2              lock



12년 9월 10일 월요일
데드락(2/2)
     •   해결 방법


          •   상호배제(Mutual exclusion)


                 •   스레드 수 이상으로 자원을 늘려서 해결 가능: 일반적으로 힘듬


          •   잠금&대기(Lock&Wait)


                 •   필요한 모든 자원을 점유하지 못한다면 모든 자원을 반환하여 해결 가능


                      •   기아(Starvation), 라이브락(Livelock) 등의 문제가 발생할 수 있음


          •   선점불가(No Preemption)


                 •   자원을 소유중인 스레드에게 해제를 요청하는 메커니즘을 사용하여 해결 가능


                      •   이러한 구현 및 관리가 쉽지 않음


          •   순환대기(Circular Wait)


                 •   데드락을 방지하는 가장 흔한 전략중 하나


                 •   모든 자원을 똑같은 순서대로 할당하게 만들어 해결 가능


                      •   자원 할당 순서가 변경 불가능할 수 있음




12년 9월 10일 월요일
다중 스레드 코드 테스트

     • 다중 스레드를 테스트 하여 검증하기는 쉽지 않다


     • 권장 방법


          • 몬테 카를로 테스트


                 • 조율이 가능하게 유연한 테스트를 만들고, 임의의 값을 조율하며 반복하며 테스트


          • 시스템을 배치할 모든 플랫폼에서 테스트


          • 부하가 변하는 장비에서 테스트




12년 9월 10일 월요일

Contenu connexe

Tendances

windows via c++ Ch 5. Job
windows via c++ Ch 5. Jobwindows via c++ Ch 5. Job
windows via c++ Ch 5. JobHyosung Jeon
 
Windws via c/c++ chapter 6
Windws via c/c++ chapter 6Windws via c/c++ chapter 6
Windws via c/c++ chapter 6SukYun Yoon
 
Mastering ethereum(smart contract)
Mastering ethereum(smart contract)Mastering ethereum(smart contract)
Mastering ethereum(smart contract)제호 송
 
Multithread design pattern
Multithread design patternMultithread design pattern
Multithread design pattern종빈 오
 
Free rtos seminar
Free rtos seminarFree rtos seminar
Free rtos seminarCho Daniel
 
이더리움의 현황, 한계점 및 개선노력
이더리움의 현황, 한계점 및 개선노력 이더리움의 현황, 한계점 및 개선노력
이더리움의 현황, 한계점 및 개선노력 Younghoon Moon
 
Java 강의자료 ed11
Java 강의자료 ed11Java 강의자료 ed11
Java 강의자료 ed11hungrok
 
파이썬 병렬프로그래밍
파이썬 병렬프로그래밍파이썬 병렬프로그래밍
파이썬 병렬프로그래밍Yong Joon Moon
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)beom kyun choi
 
Startup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSStartup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSCirculus
 
Surface flingerservice(서피스플링거서비스초기화 ics)
Surface flingerservice(서피스플링거서비스초기화 ics)Surface flingerservice(서피스플링거서비스초기화 ics)
Surface flingerservice(서피스플링거서비스초기화 ics)fefe7270
 
[Windows via c/c++] 4장 프로세스
[Windows via c/c++] 4장 프로세스[Windows via c/c++] 4장 프로세스
[Windows via c/c++] 4장 프로세스종빈 오
 
Blockchain 3rd smart contract programming
Blockchain 3rd smart contract programmingBlockchain 3rd smart contract programming
Blockchain 3rd smart contract programmingihpark92
 
android_thread
android_threadandroid_thread
android_threadhandfoot
 
[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?NAVER D2
 
[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화AnselmKim
 
Surface flingerservice(서피스 출력 요청 jb)
Surface flingerservice(서피스 출력 요청 jb)Surface flingerservice(서피스 출력 요청 jb)
Surface flingerservice(서피스 출력 요청 jb)fefe7270
 

Tendances (20)

windows via c++ Ch 5. Job
windows via c++ Ch 5. Jobwindows via c++ Ch 5. Job
windows via c++ Ch 5. Job
 
Windws via c/c++ chapter 6
Windws via c/c++ chapter 6Windws via c/c++ chapter 6
Windws via c/c++ chapter 6
 
Mastering ethereum(smart contract)
Mastering ethereum(smart contract)Mastering ethereum(smart contract)
Mastering ethereum(smart contract)
 
Multithread design pattern
Multithread design patternMultithread design pattern
Multithread design pattern
 
Free rtos seminar
Free rtos seminarFree rtos seminar
Free rtos seminar
 
04 프로세스
04 프로세스04 프로세스
04 프로세스
 
Nodejs_chapter3
Nodejs_chapter3Nodejs_chapter3
Nodejs_chapter3
 
이더리움의 현황, 한계점 및 개선노력
이더리움의 현황, 한계점 및 개선노력 이더리움의 현황, 한계점 및 개선노력
이더리움의 현황, 한계점 및 개선노력
 
Java 강의자료 ed11
Java 강의자료 ed11Java 강의자료 ed11
Java 강의자료 ed11
 
파이썬 병렬프로그래밍
파이썬 병렬프로그래밍파이썬 병렬프로그래밍
파이썬 병렬프로그래밍
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)
 
Gcd ppt
Gcd pptGcd ppt
Gcd ppt
 
Startup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSStartup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JS
 
Surface flingerservice(서피스플링거서비스초기화 ics)
Surface flingerservice(서피스플링거서비스초기화 ics)Surface flingerservice(서피스플링거서비스초기화 ics)
Surface flingerservice(서피스플링거서비스초기화 ics)
 
[Windows via c/c++] 4장 프로세스
[Windows via c/c++] 4장 프로세스[Windows via c/c++] 4장 프로세스
[Windows via c/c++] 4장 프로세스
 
Blockchain 3rd smart contract programming
Blockchain 3rd smart contract programmingBlockchain 3rd smart contract programming
Blockchain 3rd smart contract programming
 
android_thread
android_threadandroid_thread
android_thread
 
[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?
 
[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화
 
Surface flingerservice(서피스 출력 요청 jb)
Surface flingerservice(서피스 출력 요청 jb)Surface flingerservice(서피스 출력 요청 jb)
Surface flingerservice(서피스 출력 요청 jb)
 

En vedette

프로그래머로사는법 Ch17
프로그래머로사는법 Ch17프로그래머로사는법 Ch17
프로그래머로사는법 Ch17HyeonSeok Choi
 
Refactoring 메소드 호출의 단순화
Refactoring 메소드 호출의 단순화Refactoring 메소드 호출의 단순화
Refactoring 메소드 호출의 단순화HyeonSeok Choi
 
Domain driven design ch1
Domain driven design ch1Domain driven design ch1
Domain driven design ch1HyeonSeok Choi
 
컴퓨터 프로그램의 구조와 해석 1.2
컴퓨터  프로그램의 구조와 해석 1.2컴퓨터  프로그램의 구조와 해석 1.2
컴퓨터 프로그램의 구조와 해석 1.2HyeonSeok Choi
 
Nodejs 프로그래밍 ch.3
Nodejs 프로그래밍 ch.3Nodejs 프로그래밍 ch.3
Nodejs 프로그래밍 ch.3HyeonSeok Choi
 
Mining the social web ch1
Mining the social web ch1Mining the social web ch1
Mining the social web ch1HyeonSeok Choi
 

En vedette (8)

프로그래머로사는법 Ch17
프로그래머로사는법 Ch17프로그래머로사는법 Ch17
프로그래머로사는법 Ch17
 
Refactoring_1_4
Refactoring_1_4Refactoring_1_4
Refactoring_1_4
 
Refactoring 메소드 호출의 단순화
Refactoring 메소드 호출의 단순화Refactoring 메소드 호출의 단순화
Refactoring 메소드 호출의 단순화
 
Domain driven design ch1
Domain driven design ch1Domain driven design ch1
Domain driven design ch1
 
컴퓨터 프로그램의 구조와 해석 1.2
컴퓨터  프로그램의 구조와 해석 1.2컴퓨터  프로그램의 구조와 해석 1.2
컴퓨터 프로그램의 구조와 해석 1.2
 
Nodejs 프로그래밍 ch.3
Nodejs 프로그래밍 ch.3Nodejs 프로그래밍 ch.3
Nodejs 프로그래밍 ch.3
 
Code1_2
Code1_2Code1_2
Code1_2
 
Mining the social web ch1
Mining the social web ch1Mining the social web ch1
Mining the social web ch1
 

Similaire à Clean code appendix 1

Introduction to Fork Join Framework_SYS4U I&C
Introduction to Fork Join Framework_SYS4U I&CIntroduction to Fork Join Framework_SYS4U I&C
Introduction to Fork Join Framework_SYS4U I&Csys4u
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기jongho jeong
 
Pinpoint spring_camp 2015
Pinpoint spring_camp 2015Pinpoint spring_camp 2015
Pinpoint spring_camp 2015Woonduk-Kang
 
C# Game Server
C# Game ServerC# Game Server
C# Game Serverlactrious
 
12장 상속 (고급)
12장 상속 (고급)12장 상속 (고급)
12장 상속 (고급)유석 남
 
[Hello world 오픈세미나]open api client개발
[Hello world 오픈세미나]open api client개발[Hello world 오픈세미나]open api client개발
[Hello world 오픈세미나]open api client개발NAVER D2
 
Sonarqube 20160509
Sonarqube 20160509Sonarqube 20160509
Sonarqube 20160509영석 조
 
.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기Seong Won Mun
 
KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기
KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기
KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기흥배 최
 
Node.js 팀 스터디 발표자료.
Node.js 팀 스터디 발표자료.Node.js 팀 스터디 발표자료.
Node.js 팀 스터디 발표자료.SeungWoo Lee
 
Multi-thread : producer - consumer
Multi-thread : producer - consumerMulti-thread : producer - consumer
Multi-thread : producer - consumerChang Yoon Oh
 
실용주의 디자인패턴 2 인터페이스로 프로그래밍하기
실용주의 디자인패턴   2 인터페이스로 프로그래밍하기실용주의 디자인패턴   2 인터페이스로 프로그래밍하기
실용주의 디자인패턴 2 인터페이스로 프로그래밍하기Cosmos Shin
 
[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요
[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요
[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요NAVER D2
 
파이썬 데이터베이스 연결 1탄
파이썬 데이터베이스 연결 1탄파이썬 데이터베이스 연결 1탄
파이썬 데이터베이스 연결 1탄SeongHyun Ahn
 
120908 레거시코드활용전략 4장5장
120908 레거시코드활용전략 4장5장120908 레거시코드활용전략 4장5장
120908 레거시코드활용전략 4장5장tedypicker
 
스프링 어플리케이션의 문제해결사례와 안티패턴
스프링 어플리케이션의 문제해결사례와 안티패턴스프링 어플리케이션의 문제해결사례와 안티패턴
스프링 어플리케이션의 문제해결사례와 안티패턴Sanghyuk Jung
 
11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례
11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례
11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례YongSung Yoon
 

Similaire à Clean code appendix 1 (20)

Introduction to Fork Join Framework_SYS4U I&C
Introduction to Fork Join Framework_SYS4U I&CIntroduction to Fork Join Framework_SYS4U I&C
Introduction to Fork Join Framework_SYS4U I&C
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기
 
Pinpoint spring_camp 2015
Pinpoint spring_camp 2015Pinpoint spring_camp 2015
Pinpoint spring_camp 2015
 
C# Game Server
C# Game ServerC# Game Server
C# Game Server
 
JDK 변천사
JDK 변천사JDK 변천사
JDK 변천사
 
Rx java essentials
Rx java essentialsRx java essentials
Rx java essentials
 
12장 상속 (고급)
12장 상속 (고급)12장 상속 (고급)
12장 상속 (고급)
 
[Hello world 오픈세미나]open api client개발
[Hello world 오픈세미나]open api client개발[Hello world 오픈세미나]open api client개발
[Hello world 오픈세미나]open api client개발
 
Sonarqube 20160509
Sonarqube 20160509Sonarqube 20160509
Sonarqube 20160509
 
.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기
 
KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기
KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기
KGC 2016 오픈소스 네트워크 엔진 Super socket 사용하기
 
Node.js 팀 스터디 발표자료.
Node.js 팀 스터디 발표자료.Node.js 팀 스터디 발표자료.
Node.js 팀 스터디 발표자료.
 
Multi-thread : producer - consumer
Multi-thread : producer - consumerMulti-thread : producer - consumer
Multi-thread : producer - consumer
 
실용주의 디자인패턴 2 인터페이스로 프로그래밍하기
실용주의 디자인패턴   2 인터페이스로 프로그래밍하기실용주의 디자인패턴   2 인터페이스로 프로그래밍하기
실용주의 디자인패턴 2 인터페이스로 프로그래밍하기
 
[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요
[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요
[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요
 
파이썬 데이터베이스 연결 1탄
파이썬 데이터베이스 연결 1탄파이썬 데이터베이스 연결 1탄
파이썬 데이터베이스 연결 1탄
 
120908 레거시코드활용전략 4장5장
120908 레거시코드활용전략 4장5장120908 레거시코드활용전략 4장5장
120908 레거시코드활용전략 4장5장
 
Realm @Android
Realm @Android Realm @Android
Realm @Android
 
스프링 어플리케이션의 문제해결사례와 안티패턴
스프링 어플리케이션의 문제해결사례와 안티패턴스프링 어플리케이션의 문제해결사례와 안티패턴
스프링 어플리케이션의 문제해결사례와 안티패턴
 
11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례
11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례
11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례
 

Plus de HyeonSeok Choi

밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05HyeonSeok Choi
 
밑바닥부터시작하는딥러닝 Ch2
밑바닥부터시작하는딥러닝 Ch2밑바닥부터시작하는딥러닝 Ch2
밑바닥부터시작하는딥러닝 Ch2HyeonSeok Choi
 
프로그래머를위한선형대수학1.2
프로그래머를위한선형대수학1.2프로그래머를위한선형대수학1.2
프로그래머를위한선형대수학1.2HyeonSeok Choi
 
알고리즘 중심의 머신러닝 가이드 Ch04
알고리즘 중심의 머신러닝 가이드 Ch04알고리즘 중심의 머신러닝 가이드 Ch04
알고리즘 중심의 머신러닝 가이드 Ch04HyeonSeok Choi
 
딥러닝 제대로시작하기 Ch04
딥러닝 제대로시작하기 Ch04딥러닝 제대로시작하기 Ch04
딥러닝 제대로시작하기 Ch04HyeonSeok Choi
 
밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05HyeonSeok Choi
 
7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성HyeonSeok Choi
 
7가지 동시성 모델 4장
7가지 동시성 모델 4장7가지 동시성 모델 4장
7가지 동시성 모델 4장HyeonSeok Choi
 
실무로 배우는 시스템 성능 최적화 Ch8
실무로 배우는 시스템 성능 최적화 Ch8실무로 배우는 시스템 성능 최적화 Ch8
실무로 배우는 시스템 성능 최적화 Ch8HyeonSeok Choi
 
실무로 배우는 시스템 성능 최적화 Ch7
실무로 배우는 시스템 성능 최적화 Ch7실무로 배우는 시스템 성능 최적화 Ch7
실무로 배우는 시스템 성능 최적화 Ch7HyeonSeok Choi
 
실무로 배우는 시스템 성능 최적화 Ch6
실무로 배우는 시스템 성능 최적화 Ch6실무로 배우는 시스템 성능 최적화 Ch6
실무로 배우는 시스템 성능 최적화 Ch6HyeonSeok Choi
 
Logstash, ElasticSearch, Kibana
Logstash, ElasticSearch, KibanaLogstash, ElasticSearch, Kibana
Logstash, ElasticSearch, KibanaHyeonSeok Choi
 
실무로배우는시스템성능최적화 Ch1
실무로배우는시스템성능최적화 Ch1실무로배우는시스템성능최적화 Ch1
실무로배우는시스템성능최적화 Ch1HyeonSeok Choi
 
HTTP 완벽가이드 21장
HTTP 완벽가이드 21장HTTP 완벽가이드 21장
HTTP 완벽가이드 21장HyeonSeok Choi
 
HTTP 완벽가이드 16장
HTTP 완벽가이드 16장HTTP 완벽가이드 16장
HTTP 완벽가이드 16장HyeonSeok Choi
 

Plus de HyeonSeok Choi (20)

밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05
 
밑바닥부터시작하는딥러닝 Ch2
밑바닥부터시작하는딥러닝 Ch2밑바닥부터시작하는딥러닝 Ch2
밑바닥부터시작하는딥러닝 Ch2
 
프로그래머를위한선형대수학1.2
프로그래머를위한선형대수학1.2프로그래머를위한선형대수학1.2
프로그래머를위한선형대수학1.2
 
알고리즘 중심의 머신러닝 가이드 Ch04
알고리즘 중심의 머신러닝 가이드 Ch04알고리즘 중심의 머신러닝 가이드 Ch04
알고리즘 중심의 머신러닝 가이드 Ch04
 
딥러닝 제대로시작하기 Ch04
딥러닝 제대로시작하기 Ch04딥러닝 제대로시작하기 Ch04
딥러닝 제대로시작하기 Ch04
 
밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05
 
함수적 사고 2장
함수적 사고 2장함수적 사고 2장
함수적 사고 2장
 
7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성
 
7가지 동시성 모델 4장
7가지 동시성 모델 4장7가지 동시성 모델 4장
7가지 동시성 모델 4장
 
Bounded Context
Bounded ContextBounded Context
Bounded Context
 
DDD Repository
DDD RepositoryDDD Repository
DDD Repository
 
DDD Start Ch#3
DDD Start Ch#3DDD Start Ch#3
DDD Start Ch#3
 
실무로 배우는 시스템 성능 최적화 Ch8
실무로 배우는 시스템 성능 최적화 Ch8실무로 배우는 시스템 성능 최적화 Ch8
실무로 배우는 시스템 성능 최적화 Ch8
 
실무로 배우는 시스템 성능 최적화 Ch7
실무로 배우는 시스템 성능 최적화 Ch7실무로 배우는 시스템 성능 최적화 Ch7
실무로 배우는 시스템 성능 최적화 Ch7
 
실무로 배우는 시스템 성능 최적화 Ch6
실무로 배우는 시스템 성능 최적화 Ch6실무로 배우는 시스템 성능 최적화 Ch6
실무로 배우는 시스템 성능 최적화 Ch6
 
Logstash, ElasticSearch, Kibana
Logstash, ElasticSearch, KibanaLogstash, ElasticSearch, Kibana
Logstash, ElasticSearch, Kibana
 
실무로배우는시스템성능최적화 Ch1
실무로배우는시스템성능최적화 Ch1실무로배우는시스템성능최적화 Ch1
실무로배우는시스템성능최적화 Ch1
 
HTTP 완벽가이드 21장
HTTP 완벽가이드 21장HTTP 완벽가이드 21장
HTTP 완벽가이드 21장
 
HTTP 완벽가이드 16장
HTTP 완벽가이드 16장HTTP 완벽가이드 16장
HTTP 완벽가이드 16장
 
HTTPS
HTTPSHTTPS
HTTPS
 

Clean code appendix 1

  • 1. Appendix-A 동시성 II chois79 12년 9월 10일 월요일
  • 2. Review of Chapter-13 동시성 I • 다중 스레드(동시성) 코드는 올바로 구현하기가 어렵다 • 동시성의 오해 • 동시성은 항상 성능을 높여준다 • 동시성을 구현해도 설계는 변하지 않는다 • 동기화 라이브러리를 사용하면 동시성을 이해할 필요가 없다 • 동시성 방어 원칙 • SRP(단일 책임 원칙): 동시성은 복잡성 하나만으로도 따로 분리할 이유가 충분 • 공유 데이터의 최소화 및 캡슐화 • 복사본을 사용 • 스레드는 가능한한 독립적으로 구현 • 동시성 구현 코드 테스트 • 완벽한 증명하기는 현실적으로 불가능 • 많은 플랫폼에서 많은 구성으로 반복해서 테스트가 필요 12년 9월 10일 월요일
  • 3. 클라이언트/서버 예제(1/4) • Non-Thread Version ServerSocket serverSocket = new ServerSocket(8009); while (keepProcessing) { try { Socket socket = serverSocket.accept(); process(socket); } catch (Exception e) { handle(e); } } • 만약 성능 이슈가 발생한다면? • 응용 프로그램의 수행시간 종류 • 프로세서 - 수치 계산, 정규 표현식 처리, 가비지 컬렉션 • I/O - 소켓 사용, 데이터 베이스 연결, 가상 메모리 스와핑 기다리기 • 멀티 스레드로 성능 개선 가능 12년 9월 10일 월요일
  • 4. 클라이언트/서버 예제(2/4) • Thread Version void process(final Socket socket) { if (socket == null) return; Runnable clientHandler = new Runnable() { public void run() { try { String message = MessageUtils.getMessage(socket); MessageUtils.sendMessage(socket, "Processed: " + message); closeIgnoringException(socket); } catch (Exception e) { e.printStackTrace(); } } }; Thread clientConnection = new Thread(clientHandler); clientConnection.start(); } • 이 코드의 문제점 • 하나 이상의 책임: 소켓 연결 관리, 클라이언트 처리, 스레드 정책, 서버 종료 정책 • 다양한 추상화 수준 12년 9월 10일 월요일
  • 5. 클라이언트/서버 예제(3/4) • 책임별로 클래스를 분리 • ClientConnection: 소켓 연결 관리 • ClientRequestProcessor: 클라이언트 처리 • ClientScheduler: 스레드 정책 • ConnectionManager: 서버 종료 정책 public void run() { while (keepProcessing) { try { ClientConnection clientConnection = connectionManager.awaitClient(); ClientRequestProcessor requestProcessor = new ClientRequestProcessor(clientConnection); clientScheduler.schedule(requestProcessor); } catch (Exception e) { e.printStackTrace(); } } connectionManager.shutdown(); } 12년 9월 10일 월요일
  • 6. 클라이언트/서버 예제(4/4) • 스레드 정책 코드 및 확장 public interface ClientScheduler { public void schedule(ClientRequestProcessor requestProcessor); } public class ThreadPerRequestScheduler implements ClientScheduler { @Override public void schedule(final ClientRequestProcessor requestProcessor) { Runnable runnable = new Runnable() { public void run() { requestProcessor.process(); } }; Thread thread = new Thread(runnable); thread.start(); } } // Java Executor framework을 사용한 Thread 정책 변경 public class ExecutorClientScheduler implements ClientScheduler { Executor executor; public ExecutorClientScheduler(int availableThreads) { executor = Executors.newFixedThreadPool(availableThreads); } public void schedule(final ClientRequestProcessor requestProcessor) { Runnable runnable = new Runnable() { public void run() { requestProcessor.process(); } }; executor.execute(runnable); } } 12년 9월 10일 월요일
  • 7. 가능한 실행 경로(1/2) • 2개의 스레드로 이 코드를 실행한다면? public class IdGenerator { int lastIdUsed; public int incrementValue() { return ++lastIdUsed; } } • lastIdUsed의 초기값이 93일 경우 • 스레드 1이 94를 얻고, 스레드 2가 95를 얻고, lastIdUsed가 95가 된다 • 스레드 1이 95를 얻고, 스레드 2가 94를 얻고, lastIdUsed가 95가 된다 • 스레드 1이 94를 얻고, 스레드 2가 94를 얻고, lastIdUsed가 94가 된다 • JVM의 구현 방식에 따라 이 결과도 가능 12년 9월 10일 월요일
  • 8. 가능한 실행 경로(2/2) • 경로의 수 • return ++lastIdUsed는 바이트 코드 8개로 구성됨 • 루프나 분기가 없이 명령 N개를 T개의 스레드로 실행했을때 가능한 경로의 수 • Ex) N = 8이고, T = 2이면 가능한 경로의 수: 12,870 • Synchronized를 적용했을 경우 • 가능한 경로의 수: 2(T) public synchronized int incrementValue() { return ++lastIdUsed; } 12년 9월 10일 월요일
  • 9. 라이브러리를 이해하라(1/3) • Executor 프레임워크 • 스레드 풀 관리 • Runnable 인터페이스 지원 • Callable/Future 인터페이스 지원 • 스레드의 수행 결과를 받아오기 위해 사용 public String processRequest(String message) throws Exception { Callable<String> makeExternalCall = new Callable<String>() { public String call() throws Exception { String result = ""; // make external request return result; } }; Future<String> result = executorService.submit(makeExternalCall); String partialResult = doSomeLocalProcessing(); return result.get() + partialResult; } 12년 9월 10일 월요일
  • 10. 라이브러리를 이해하라(2/3) • 스레드를 중단하지 않는 방법 • Synchronized 및 Lock • 비관적 잠금: 항상 락을 사용 public class ObjectWithValue { private int value; public synchronized void incrementValue() { ++value;} public int getValue() { return value; } } • AtomicInteger 사용 - Concurrent package • 낙관적 잠금: 현재 변수 값이 최종으로 알려진 값일 경우 갱신하고, 그렇지 않을 경우 성공할때까지 재 시도 • 프로세서의 CAS(Compare And Swap) 연산을 사용 public class ObjectWithValue { private AtomicInteger value = new AtomicInteger(); public void incrementValue() { value.incrementAndGet(); } public int getValue() { return value.get(); } // CAS의 구현 int variableBeingSet; void simulateNonBlockingSet(int newValue) { int currentValue; do { currentValue = variableBeingSet; } while (currentValue != compareAndSwap(currentValue, newValue)); } 12년 9월 10일 월요일
  • 11. 라이브러리를 이해하라(3/3) • 스레드에 안전하지 않은 클래스 • SimpleDateFormat, java.util 컨테이너 클래스... • 해결 방안 • 스레드 안전 라이브러리 사용 • 직접 구현 • 클라이언트 기반 잠금 메커니즘 • 공유 데이터를 사용하는 모든 곳에서 lock을 사용 • 서버 기반 잠금 메커니즘 • 공유 데이터에 접근을 제어하는 별도의 클래스로 랩핑 12년 9월 10일 월요일
  • 12. 메소드 사이에 존재하는 의존성을 조심하라(1/3) • 의존성 예제 • 여러 메소드에서 하나의 변수를 공유해서 사용 public class IntegerIterator implements Iterator<Integer> { private Integer nextValue = 0; public synchronized boolean hasNext() { return nextValue < 100000; } public synchronized Integer next() { if (nextValue == 100000) throw new IteratorPastEndException(); return nextValue++; } public synchronized Integer getNextValue() { return nextValue; } } • 만약 다중 스레드가 IntegerIterator 인스턴스 하나를 공유 한다면? while(iterator.hasNext()) { int nextValue = iterator.next(); // nextValue로 뭔가를 한 } 오류 발생: nextValue가 100000을 넘을 가능성이 존재 12년 9월 10일 월요일
  • 13. 메소드 사이에 존재하는 의존성을 조심하라(2/3) • 해결책 • 실패를 용인 • 클라이언트 기반 잠금: 모든 클라이언트에서 동기화 로직 구현 • DRY(Don’t Repeat Yourself) 원칙 위반: 중복으로 인한 오류 발생이 쉬움 while (true) { int nextValue; Client-based synchronized (iterator) { if (!iterator.hasNext()) break; nextValue = iterator.next(); } doSometingWith(nextValue); Server-based } public class IntegerIteratorServerLocked { private Integer nextValue = 0; public synchronized Integer getNextOrNull() { • 서버 기반 잠금 if (nextValue < 100000) return nextValue++; • 코드 중복이 줄어듬: 오류가 발생할 가능성이 줄어듬 else return null; } • 성능이 좋아짐 } while (true) { • 스레드 정책이 하나임 int nextValue = iterator.getNextOrNull();; if (next == null) • 공유 변수가 줄어든다 break; doSometingWith(nextValue); } 12년 9월 10일 월요일
  • 14. 메소드 사이에 존재하는 의존성을 조심하라(3/3) • 서버 코드에 손대지 못하는 경우 • Adapter 패턴을 적용 public class ThreadSafeIntegerIterator { private IntegerIterator iterator = new IntegerIterator(); public synchronized Integer getNextOrNull() { if (iterator.hasNext()) return iterator.next(); return null; } } 12년 9월 10일 월요일
  • 15. 작업 처리량 높이기 • EX) 네트워크에서 페이지를 읽어 분석하는 프로그램 • 가정 • 페이지를 읽어 오는 평균 I/O 시간: 1초 • 페이지를 분석하는 평균 처리시간: 0.5초 • 처리는 CPU 100% 사용, I/O는 CPU 0% 사용 • 단일 스레드 환경 • N 페이지를 처리하는 총 실행시간: 1.5초 * N • 멀티 스레드 환경 • 3개의 스레드로 동시에 실행한다면? • I/O 1초동안 다른 2개의 스레드는 페이지를 분석할 수 있어 단일 스레드에 비해 약 3배의 처리 속도를 가짐 12년 9월 10일 월요일
  • 16. 데드락(1/2) • 4가지 조건을 모두 만족하는 경우 데드락 발생 • 상호배제(Mutual exclusion) use Thread#1 Res1 Thread#2 not use • 잠금&대기(Lock&Wait) use Thread#1 Res1 Thread#2 wait • 선점불가(No Preemption) use Thread#1 Res1 Thread#2 not preemptive • 순환대기(Circular Wait) lock Res1 request Thread#2 Thread#1 request Res2 lock 12년 9월 10일 월요일
  • 17. 데드락(2/2) • 해결 방법 • 상호배제(Mutual exclusion) • 스레드 수 이상으로 자원을 늘려서 해결 가능: 일반적으로 힘듬 • 잠금&대기(Lock&Wait) • 필요한 모든 자원을 점유하지 못한다면 모든 자원을 반환하여 해결 가능 • 기아(Starvation), 라이브락(Livelock) 등의 문제가 발생할 수 있음 • 선점불가(No Preemption) • 자원을 소유중인 스레드에게 해제를 요청하는 메커니즘을 사용하여 해결 가능 • 이러한 구현 및 관리가 쉽지 않음 • 순환대기(Circular Wait) • 데드락을 방지하는 가장 흔한 전략중 하나 • 모든 자원을 똑같은 순서대로 할당하게 만들어 해결 가능 • 자원 할당 순서가 변경 불가능할 수 있음 12년 9월 10일 월요일
  • 18. 다중 스레드 코드 테스트 • 다중 스레드를 테스트 하여 검증하기는 쉽지 않다 • 권장 방법 • 몬테 카를로 테스트 • 조율이 가능하게 유연한 테스트를 만들고, 임의의 값을 조율하며 반복하며 테스트 • 시스템을 배치할 모든 플랫폼에서 테스트 • 부하가 변하는 장비에서 테스트 12년 9월 10일 월요일