2015. 1. 26.

[OS]쓰레드(Thread)와 Critical Section(임계영역)

 
 쓰레드에 대한 기본적인 지식을 바탕으로 쓰레드의 특성에 대해 좀더 살펴보고자 한다. 메모리 관점에서 본 쓰레드에 대한 지식이 있다면 이해하기 편할 것이다.


프로세스와 메인 쓰레드(main thread)

  쓰레드는 프로세스에 존재하는 실행 흐름 중 하나이다. 그런 실행 흐름 중에는 우리가 흔히 main() 함수라고 부르는 쓰레드가 존재한다. 어떤 프로그램을 실행시키면 main() 함수가 실행되는데, 이는 다시 말해 main 쓰레드가 실행된다는 것을 의미한다.  만약 main 쓰레드를 통해서 다른 쓰레드를 만들어서 다른 쓰레드로 하여금 특정한 일을 시키면 어떨까? 이 상황은 아래의 그림과 같다.(쓰레드의 의미 중에 실, 가닥이라는 의미도 있다)

 
<출처: http://www.onlinebuff.com/article_understand-threading-and-types-of-threading-in-c-using-an-example_56.html>

 
 main 쓰레드는 프로세스가 실행되면 자동적으로 실행되는 thread이다. 그림에 등장하는 worker 쓰레드는 main 쓰레드가 생성한 새로운 쓰레드이다. 새로운 worker 쓰레드는 main 쓰레드와는 별개로 자신의 고유한 작업 흐름을 가진다.

 
 그런데 메모리 관점에서 본 쓰레드를 떠올려 보면 쓰레드는 heap, data 영역을 공유한다는 것을 알 수 있다. 고유한 작업 흐름을 가지는데 메모리를 공유한다는 점에 주목해야 한다.


 
 
쓰레드를 사용하여 실행흐름을 분할 

 
 만약 어떤 사람이 0 ~ 100,000 사이의 숫자의 총합을 구하고자 한다. 이 사람은 thread의 대한 지식을 가지고 있었다. 이 사람은 0 ~ 33,333까지의 합을 thread1로 처리하고, 33,334 ~ 66,666까지의 합은 thread2로 처리하고, 66,667 ~ 100,000가지의 합은 thread3으로 처리해야겠다고 생각하였다. 하나의 thread로 0 ~ 100,000까지의 합을 구하는 것보다는 실행흐름을 3개로 나누고, 3개의 실행 흐름을 병렬적으로 수행하면 합을 구하는 시간이 줄어들 것으로 예상한 것이다. 얼핏 들으면 매우 그럴듯한 발상이다. 하지만 이를 그대로 코드로 옮기면 문제가 발생한다.


 ThreadProc() 함수 바로 앞에 선언된 total은 static 변수이다. static 변수는 메모리의 data 영역에 존재하고, thread는 이를 공유하게 된다. 결국 3개의 쓰레드는 모두 static 변수 total에 접근가능하다. 이런 특성때문에 쓰레드는 IPC와 같은 방법으로 통신할 필요가 없다.

 하지만 위 total 변수는 쓰레드의 동시접근 문제를 발생시킬 수 있다.

 쓰레드는 결국 스케줄러에 의해 번갈아가며 실행된다. 이 과정에서 컨텍스트 스위칭은 불가피하게 발생한다. 프로세스는 독립적인 메모리 공간을 가지기 때문에 컨텍스트 스위칭 과정에서 데이터가 변경되지는 않는다. 하지만 쓰레드 간의 컨텍스트 스위칭은 상황이 다르다. 컨텍스트 스위칭 상황에서 쓰레드는 프로그램 라인 단위로 이뤄지지 않는다. 예를 들어 A() 함수가 실행 중 일 때는 절대 컨텍스트 스위칭이 발생하지 않는다고 생각하면 안 된다. 실행 중인 쓰레드의 변경은 매우 빈번하게 발생하며, 우리가 이에 쓰레드의 실행 흐름을 예측해서 제어하는 것은 불가능하다.

 그래서 둘 이상의 쓰레드가 위의 total과 같이 같은 메모리 영역을 동시에 참조하면 문제를 일으킬 수 있다. 우리는 덧셈이 올바르게 완료될 것으로 예상하지만, 이는 우리의 기대일 뿐이다. 1 + 2의 값을 3이라고 저장하지도 못한 상태에서 33,334 + 33,335를 계산하는 쓰레드가 실행될지도 모른다. 이렇게 되면 결국 total의 값은 3만큼 누락된다.


임계영역(Critical Section)

 위 코드의 worker 쓰레드 함수 내부의 total을 둘 이상의 쓰레드가 동시에 실행할 경우 문제가 발생할 수 있다. 이런 문제를 일으킬 수 있는 코드 블럭을 임계영역이라고 한다. 다시 말해 임계영역은 배타적 접근(한 순간에 하나의 쓰레드만 접근)이 요구되는 공유 리소스(전역변수, static 변수 등)에 접근하는 코드 블럭을 의미한다.
 
출처 : https://mooneegee.blogspot.com/2015/01/

 

'OS' 카테고리의 다른 글

컨텍스트 스위칭  (0) 2018.08.08
OS 학습 참고  (0) 2018.08.08
메모리 관점에서 본 쓰레드(thread)  (0) 2018.08.08
세마포어 뮤텍스  (0) 2018.08.08

여러 쓰레드들은 자원을 공유하고, 프로세스간 메시지를 전송하면서 간혹 문제가 발생할 수 있습니다.

 

즉, 공유된 자원에 여러 프로세스 , 쓰레드가 동시에 접근하면서 문제가 발생합니다. 

공유된 자원 속 하나의 데이터는 한번에 하나의 프로세스만 접근할 수 있도록 제한해 두어야 할 필요성이 있는데

이를 위해 고안된 것이 Semaphore(세마포어)입니다.

 

유명한 화장실 예제로 쉽게 설명해보겠습니다.

 

공중 화장실은 한번에 1명만 사용할 수 있다고 가정하겠습니다.

어떤 사람이 사용하고 있는데 다른 누군가가 갑자기 들어와서 같이 쓰자고 하면... 생각만해도 이상하지요..?

이를 막기 위해 화장실 열쇠를 만들 수 있습니다.

열쇠를 가지고 있는 한 사람만 화장실을 이용하고, 열쇠가 없는 사람은 밖에서 대기를 하죠.

 

여기서 열쇠는 세마포어와 같은 역할을 한다고 할 수 있습니다.

 

그럼 세마포터와 뮤텍스 각각 어떤 의미를 가지고 있을까요?

 

 

Semaphore(세마포어)

 

공유된 자원의 데이터를 여러 프로세스가 접근하는 것을 막는 것!

 

그리고 세마포어는 리소스의 상태를 나타내는 간단한 카운터라고 할 수 있습니다.

일반적으로 비교적 긴 시간을 확보하는 리소스에 대해 이용하게 되며, 유닉스 시스템의 프로그래밍에서 세마포어는 운영체제의 리소스를 경쟁적으로 사용하는

다중 프로세스에서 행동을 조정하거나 또는 동기화 시키는 기술입니다.

 

위 화장실 예제로 다시 살펴보면, 세마포어는 1개 이상의 열쇠라고 할 수 있습니다.

만약 화장실 칸이 4개이고 열쇠가 4개라면, 4명까지는 대기없이 바로 사용할 수 있고 

그 다음 부터는 대기를 해야하죠. 이것이 바로 세마포어입니다.

 

그러므로 몇개의 세마포어로 구성해서 운영체제의 리소스를 경쟁적으로 사용할지는 꽤 중요한 이슈입니다.

그림으로 표현하면 아래와 같습니다.

 

 

Mutex(뮤텍스, 상호배제)

 

공유된 자원의 데이터를 여러 쓰레드가 접근하는 것을 막는 것!

 

즉, *Critical Section을 가진 쓰레드들의 Running tme이 서로 겹치지 않게 각각 단독으로 실행되게 하는 기술입니다. 

다중 프로세스들이 공유 리소스에 대한 접근을 조율하기 위해 locking과 unlocking을 사용합니다.

 

간단히 말해, Mutex객체를 두 쓰레드가 동시에 사용할 수 없다는 말입니다.

 

위 화장실 예제로 다시 살펴보면, 뮤텍스는 무조건 1개의 열쇠만 가질 수 있습니다!

 

그림으로 표현하면 아래와 같습니다.

 

 

 

*Critical Section

 

다중 프로그래밍 운영체제에서 여러 프로세스가 데이터를 공유하면서 수행될 때,

각 프로세스에서 공유데이터를 엑세스하는 프로그램 코드부분을 말합니다.

 

공유데이터를 여러 프로세스가 동시에 엑세스하면 시간적인 차이 때문에 잘못된 결과를 만들수 있습니다.

이를 막기 위해 한 프로세스가 위험부분을 수행하고 있을 때, 즉 공유데이터를 액세스하고 있을 때는 

다른 프로세스들은 절대로 그 데이터를 접근할 수 없도록 해야합니다. 

 

 

세마포어와 뮤텍스의 차이?

 

세마포어는 뮤텍스가 될수 있지만, 뮤텍스는 세마포어가 될 수 없습니다.

 

뮤텍스는 항상 열쇠 1개이고, 세마포어는 여러개 가질 수 있기 때문에 

세마포어의 열쇠가 1개라면 뮤텍스와 같습니다.

 

마포어는 파일시스템 상 파일형태로 존재, 뮤텍스는 프로세스 범위입니다.

즉, 프로세스가 사라질 때 뮤텍스는 clean up 됩니다.

 

세마포어는 소유할 수 없는 반면, 뮤텍스는 소유할 수 있습니다.

 

뮤텍스의 경우, 뮤텍스를 소유하고 있는 쓰레드가 이 뮤텍스를 해제할 수 있습니다.

반면, 세마포어의 경우, 세마포어를 소유하고 있지 않은 쓰레드도 이 세마포어를 해제할 수 있습니다.

 

 

출처 : http://sycho-lego.tistory.com/11

'OS' 카테고리의 다른 글

컨텍스트 스위칭  (0) 2018.08.08
OS 학습 참고  (0) 2018.08.08
메모리 관점에서 본 쓰레드(thread)  (0) 2018.08.08
쓰레디와 임계영역  (0) 2018.08.08

Spring Boot 시작하기 

- #9. Srping Boot JSP ModelAndView 설정하기



8장에 이어 ModelAndView 를 이용해 jstl로 데이터를 연동하는 진행해 보겠습니다.



ModelAndViewTestController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.example.controller;
 
import java.util.ArrayList;
import java.util.List;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
 
@Controller
public class ModelAndViewTestController {
   
    @RequestMapping(value="/mv")                // http://localhost/mv
    public ModelAndView root() {
        ModelAndView mv = new ModelAndView();
         
        List<string> listTest = new ArrayList<string>();
         
        listTest.add("test1");
        listTest.add("test2");
        listTest.add("test3");
         
        mv.addObject("listTest",listTest);      // jstl로 호출
        mv.addObject("ObjectTest","테스트입니다."); // jstl로 호출
        mv.setViewName("mv/testMv");         // 실제 호출될 /WEB-INF/jsp/model/testMv.jsp
        return mv;                                     
    }
}
</string></string>

** 맨 마지막줄에 </string></string> 은 무시하셔요 **


/WEB-INF/jsp/mv/testMv.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"%>
 
ModelAndView 테스트 페이지입니다.
 
<br>
 
${ObjectTest}
 
<br>
 
${listTest}
 
<br>
<br>
 
<c:foreach items="${listTest}" var="listTest">
    ${listTest} <br>
</c:foreach>


로 작성하신 후

http://localhost/mv 를 호출하시면 됩니다.



출처: http://jsijsi99.tistory.com/11?category=710810 [삽질대마왕 이대장]

 

+ Recent posts