DEV/Java

[java] 멀티스레드를 활용한 공유 메모리 구현

Bi3a 2023. 8. 17. 00:19

728x90

java 기초 깨부수기

 

 

      0. 같이 보면 좋을 포스팅

      "공유 메모리와 멀티 스레드의 이해" 포스팅에서 이어집니다.

       

      [java 기초] 공유 메모리와 멀티 스레드의 이해

      0. 이전 포스팅 : "멀티 스레드의 이해와 구현" 에서 이어지는 내용입니다. [java 기초] 멀티 스레드(Multi thread)의 이해 / 구현 1. 스레드(Thread) : 프로그램 / 프로세스 의 명령문을 위 → 아래로 차례

      doinitright.tistory.com


      저번 포스팅은 원론적인 얘기를 주로 다뤘으니 이번 포스팅에서는

      구구절절 설명 않고 구현으로 바로 넘어가겠습니다.

       

      1. 공유 메모리 및 공유 메모리를 활용할 스레드 구현

      class SharedMemory extends Thread{
          int x = 5;
          boolean isQuit = false;
      }

       

      Thread를 상속받은 공유 메모리로 사용할 스레드인 `SharedMemory` 클래스를 만들어줍니다.

      `SharedMemory` 클래스가 가지고 있으며, 스레드 간 메모리로 활용할 필드는 2개입니다.

      • int형 변수 `x`: 초기값 세팅
      • boolean형 변수 `isQuit` : 초기값 세팅

       

       

      다음으로는 공유 메모리를 활용할 스레드 2개를 만들어줍니다.

      class PlusThread extends Thread{
          SharedMemory shmem; // 필드로 SharedMemory 클래스 인스턴스를 선언
          /* shmem의 필드 변수 int x, boolean isQuit */
          public void run(){
              try{
                  while(!shmem.isQuit){ // shmem의 필드 isQuit이 false일 동안 loop
                      System.out.println("x = " + shmem.x); 
                      Thread.sleep(300); // 300ms 경과 후 
                      shmem.x++; // shmem의 필드 x값이 증가
                  }
              } catch(Exception e){
                  System.out.println(e);
          }
          }
      }

       

      • `PlusThread`는 공유 메모리 스레드 `SharedMemory` 클래스 인스턴스 `shmem`을 생성해 내부 필드로 보유합니다.
      • run() 메서드에서는 생성한 인스턴스 shmem의 필드인 int x에 대해 시간에 따라
        1. `x` 값 출력
        2. 300ms 시간 경과
        3. `x` 값 증가를 시킵니다.
      • `PlusThread`는 프로그램 실행 후 공유 메모리의 `x` 값을 시간에 따라 증가시킵니다.

       

      class MinusThread extends Thread{
          SharedMemory shmem; // 필드로 SharedMemory 클래스 인스턴스를 선언
          /* shmem의 필드 변수 int x, boolean isQuit */
          public void run(){
              Scanner sc = new Scanner(System.in); // User 입력을 위한 Scanner 호출
              while(shmem.x!=0){ // shmem의 필드 x 값이 0이 아닐동안 loop
                  sc.nextLine(); // User가 Enter키 입력시
                  System.out.println("[System] Enter가 입력되었습니다.");
                  shmem.x--; // shmem의 필드 x 값 감소
              }
              shmem.isQuit = true; // shmem의 필드 x 값이 0 도달 시 필드 isQuit = true 
              System.out.println("[System] x값이 0입니다. 당신이 이겼습니다!");
          }
      }

       

      • `MinusThread`는 공유 메모리 스레드 `SharedMemory `클래스 인스턴스 `shmem`을 생성해 내부 필드로 보유합니다.
      • run() 메소드에서는 생성한 인스턴스 `shmem`의 필드인 int x에 대해 User의 입력에 따라 
        1. `Scanner.nextln()` 으로 입력 생성
        2. 2. User가 `Enter` 입력 시 x 값 감소
        3. 3. x 값 0 도달 시 `isQuit = true`로 만들며 loop 종료
      • `MinusThread`는 프로그램 실행 후 공유 메모리의 x값을 사용자의 입력에 따라 감소시킵니다.

       

       

      마지막으로 메인을 구현해 만들어 놓은 스레드와 공유 메모리의 인스턴스를 생성하고,

      이를 연결하겠습니다.

      public class SharedMemoryTest {
          public static void main(String[] args) {
              PlusThread pt = new PlusThread(); // PlusThread 인스턴스 선언  
              MinusThread mt = new MinusThread(); // MiusThread 인스턴스 선언
              SharedMemory shobj = new SharedMemory(); // SharedMemory 인스턴스 선언
      
      	/* 공유 메모리 연결 방법 : 공유 메모리 인스턴스 생성 후 각자 스레드 내부에
              있는 필드 클래스를 공유 메모리로 참조 */
              pt.shmem = shobj;
              mt.shmem = shobj;
      
              System.out.println("[System] x가 0이 될때까지 Enter키를 누르세요.");
              
              // 스레드 클래스의 메소드 구현은 run(), 인스턴트 생성 후에 run() 호출은 start()로
              pt.start(); 
              mt.start();
          }
      }

       

      2. 결과 1 : 사용자가 Enter를 입력하지 않을 시

      [System] x가 0이 될때까지 Enter키를 누르세요.
      x = 5
      x = 6
      x = 7
      x = 8
      x = 9
      x = 10
      
      /*
      ... 이후는 x가 무한 증가하는 loop
      */

       

      3. 결과 2 : 사용자가 Enter 를 잘 입력했을 시

      [System] x가 0이 될때까지 Enter키를 누르세요.
      x = 5
      x = 6
      x = 7
      [System] Enter가 입력되었습니다.
      [System] Enter가 입력되었습니다.
      x = 6
      [System] Enter가 입력되었습니다.
      [System] Enter가 입력되었습니다.
      x = 5
      [System] Enter가 입력되었습니다.
      [System] Enter가 입력되었습니다.
      [System] Enter가 입력되었습니다.
      x = 3
      [System] Enter가 입력되었습니다.
      [System] Enter가 입력되었습니다.
      x = 2
      [System] Enter가 입력되었습니다.
      [System] Enter가 입력되었습니다.
      [System] x값이 0입니다. 당신이 이겼습니다!

       

      보시다시피 Enter키 입력에 따른 x값이 감소하는 `MinusThread` ,

      시간에 따라 x값이 증가하는 `PlusThread` 가 대립하며 작동하게 되고

      열심히 사용자가 Enter를 연타해 x값을 0으로 만들면 종료되게 됩니다.

       

      이 과정에서는 공유메모리 내의 필드인 int x와 boolean isQuit을 스레드가 공유하면서 작동함을 알 수 있습니다.

       

      물론 static으로 정적 멤버를 선언해 공유 메모리를 대체해 동일하게 구현할 수 있으나,

      추천되는 방법은 아닙니다.