220125 - 학습 정리

Suntory·2022년 1월 25일
0

TIL

목록 보기
18/57

오늘 한 일

  • 오전에 JK의 수업을 들었다. 근데 연말정산 관련해서 급한 일이 생겨서 집중을 못했다... 너무 아쉽다.
  • 코드 리뷰 시간이 있었다. 같은 그룹의 코드를 보며 다양한 방식을 접할 수 있었다. 리뷰 이후 다른 분들의 코드를 보는데 정말 대단한 분들이 많다. 대부분 거의 OS의 관점에서 구현하신 것 같아 다음에 가능하다면 그런식으로 실제 환경을 모사하는 방향으로 짜보고 싶다.

TIL

멀티 스레드 스케줄링

스레드의 개수가 코어의 수보다 많을 경우, 스레드를 어떤 순서에 의해 실행할 것인가를 결정하는 것입니다.
스레드 스케줄러에 의해 여러 스레드들이 아주 짧은 시간동안 번갈아가면서 스레드의 run() 메소드를 조금씩 실행한다.

우선순위 방식

각 스레드가 우선순위를 갖고 있고, 우선순위가 높은 스레드부터 수행시키는 형식이다.
-> 개발자가 어떤 스레드를 우선적으로 처리할 지 우선순위를 부여할 수 있다.

  • 우선순위 할당 과정
thread.setPriority(1~10);
thread.setPriority(Thread.MIN_PRIORITY);
thread.setPriority(Thread.NORM_PRIORITY);
thread.setPriority(Thread.MAX_PRIORITY);

순환 할당 방식

순환 할당방식은 시간 할당량을 정해서 하나의 스레드를 정해진 시간만큼 실행하고 다시 다른 스레드를 실행하는 방식입니다. -> 각 OS에 의해 정해진 Time slice만큼 할당하기 때문에 개발자가 임의로 수정할 수 없다.

JVM의 스레드 동작방식

JVM은 우선순위 방식의 선점형 스케줄링을 사용한다. 만약 스레드 간 서로 같은 우선순위를 가진다면, FIFO 방식으로 처리한다. 선점형 스케줄링이란 것은, 낮은 우선순위의 스레드가 Runnable로 먼저 대기하고 있더라도, 높은 우선순위의 스레드가 Runnable해지면, 낮은 우선순위의 스레드가 선점당하고, 높은 우선순위의 스레드가 실행되도록 스케줄링된다.

현재 구현한 스레드의 동작방식은 Round-Robin 방식으로 일정한 시간을 분할하여 스레드가 수행되는 식이다. 만약 우선순위로 구현해야 한다면, 어떻게 해야할 지 고민된다.

프로세스가 많아질 때 성능 향상을 위한 방법

  • 단순한 방법으로... 프로세서의 개수나 코어를 늘린다. 그럼 동시에 많은 스레드를 활용할 수 있고, 더 많은 스레드로 프로세스를 빠르게 처리할 수 있다.
  • 저번에 리눅스의 메모리 관리를 배울 때 나온 것이 Thrashing이다. 프로세스가 많아져 page fault가 자주 발생하면 운영체제는 오히려 CPU 사용률이 떨어져 더 많은 프로세스를 메모리에 올리게 된다.
    • 이를 방지하고자, Working-set 모델과 PFF 등을 활용하여 page fault를 완화시키곤 한다.
      • 이를 응용하여, 프로세스가 너무 많으면 page fault를 통한 병목현상을 줄이기 위해 할당하는 프레임 단위를 키워서 최대한 page fault를 줄이는 방법도 있을 것 같다.

setTimeout 내부 동작 방식

javascript에서 사용하는 타이머 중 하나인 setTimeout에 대해서 알아보자.
자바스크립트는 기본적으로 싱글 스레드로 동작한다. 그렇기 때문에 한 번에 한 동작밖에 할 수가 없다.
만약, setTimeout을 하고 어떤 동작을 하게되면, 이 동작은 콜스택에 올라가지 못하고 task queue에 올라가서 대기한다. 그리고 setTimeout이 끝나서 호출스택이 비면 그 다음 task queue에 있는 작업을 콜스택으로 올려 작업을 이어간다.

정확한 타이머 구현하기

단순하게 생각해서 Thread의 sleep으로 1초를 주면 될 것 같았는데, 실제로는 1초의 sleep이후 로직이 실행되는 시간까지 고려하기 때문에 1초가 아니었다. 그럼 어떻게 해야 정확한 타이머를 구현할 수 있을까?

이번에 미션을 하면서 Timer 클래스를 사용했다. Timer 클래스는 TimerTask 객체를 받아서 일정 시간간격 별로 수행할 수 있는 함수를 제공하는데, 이 때 schedule을 이용해서, Interval을 1000ms로 놓고 동작시키면 정확도가 꽤 높은 타이머를 구현할 수 있다고 한다.

멀티 스레드의 동기화 문제

멀티 프로세스, 멀티 스레드에서 공유자원을 갖고 다투는 상황을 Race condition이라고 한다. 동시에 입출력과 read가 반복되는 과정에서 접근 순서에 따라 전혀 다른 결과를 초래할 수 있기 때문에 이러한 동기화 문제가 멀티 스레드에서는 매우 중요하다.

그래서 개발자들은 mutex, sepaphore 등의 기법을 이용하여 공유자원을 관리한다.

  • mutex : 주로 on/off의 개념으로 공유자원에 lock을 걸었다 풀었다하는 개념이다. 어떤 프로세스나 스레드가 공유자원에 접근하면 mutex를 0으로 설정하고 그 동안 진입하는 스레드는 mutex가 반환될때까지 기다린다. 자원에 접근했던 스레드의 작업이 끝나면, 다시 mutex를 반납하게 되고, 대기하던 프로세스가 진입하여 작업을 이어나간다.
  • semaphore : 공유자원의 수량이 정해진 경우에 사용한다. 일종의 도서관책 같은 개념으로 생각하면 될 것 같다. 필요에 따라 대출해갔다가, 다 사용하면 반납하는 공유자원을 운용할 때 사용한다.
  • monitor : 위 두 기법은 개발자가 직접 구현해야 하기 때문에 매우 어렵다. 정확하게 구현하기도 어렵고 프로세스나 스레드 간 자발적 협력이 필요하다. (Deadlock 발생 가능성) 그래서 운영체제나 고급 언어에서는 monitor 기능을 지원해 특정 메서드나 자원에 자동으로 lock을 걸어준다. Java의 synchronized 키워드가 모니터 기법으로 동작하는 예이다.

출처

Java Thread Scheduling

개선해볼 점과 좋았던 점

  • 아침 스크럼을 하는데 조원들의 시간관리에 대해서 들을 수 있었다. 다들 시간단위를 잘 기록하고 관리하고 있는 것 같아서 본받아야겠다고 느꼈다. 막연하게 열심히 살았다 보다는 뭔가 기록을 남겨놓는 것이 동기부여도 되고 더 적나라한 열심히의 척도가 아닐까 싶다. 타이머를 잘 활용해봐야겠다.
  • 팀원들과 더 많은 소통을 하고 싶어서 적극적으로 얘기를 해보았다. 팀원들이 어떻게 느낄지 조금 걱정되지만, 그래도 그만큼 서로 얻어가는 것이 있을 것이라고 믿고 싶다.
profile
천천히, 하지만 꾸준히 그리고 열심히

0개의 댓글