달력

12

« 2024/12 »

  • 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
  • 30
  • 31

쓰레드의 동기화(synchronization)이란 뭘까? 

--> 한스레드가 진행중인 작업을 다른 쓰레드가 간석하지 못하도록 막는것을 말한다.


왜쓸까? 


싱글스레드 프로세스 경우는 프로세스 내에서 단하나의 스레드만 작업하기 때문에 

프로세스의 자원을 가지고 작업하는데 별 문제가 없다. 


하지만 

멀티스레드의경우에는 여러 스레드가 같은 프로세스 내의 자원을 공유해서 작업하기 때문에 

서로의 작업에 영향을 주게된다. 


예를들면 

ATM에 통장에 50만원이있었는데 각 다른 두곳에서 출금한다고 가정하자 ㅋㅋ 

동시에 두곳에서 50만원이 출금되면 정말 행복하겟지만.. 

은행입장에서는 큰일나는거 아닌가 ..ㅋㅋㅋ 


A atm기에서 작업을 실행할대 락을 걸어서 다른 곳은 접근못하게하고 출금이 다끝난뒤에 

접근권을 획득해서 B atm기가 출금해야 이중으로 출금되는것을 막을수있다. 

--------------------------------------------------------------------------------------------


그래서 스레드에서는 저런 일이 방지하는것을 막기위해서


한 쓰레드가 특정 작업을 끝마치기 전까지 다른 쓰레드에 의해 방해받지 않도록 하는것이 필요한데


그래서 도입된 개념이 '임계 영역(critical section)'과 '잠금(락,lock)'이다.


->공유 데이터를 사용하는 코드 영역을 임계 영역으로 지정해놓고, 공유 데이터(객체)가 

가지고 있는 lock을 획득한 단 하나의 쓰레드만 이 영역 내의 코드를 수행할 수 있게 한다.

그리고 해당 쓰레드가  임계 영역 내의; 모든 코드를 수행하고 벗어나서 lock을 반납해야만 

다른 쓰레드가 반납된 lock을 획득하여 임계 영역의 코드를 수행할 수 있게 된다. 


-------------->위에서 말한것처럼 이런 한 쓰레드가 진행 중인 작업을 다른 쓰레드가 간석하지 못하도록 막는것을!! 

'쓰레드의 동기화(Synchronization)' 라고 한다.   


동기화 방법에는 여러가지가있다. synchronized를 이용한 방식, wait ( ) , notify( ) , notifyAll( ) 를 이용한 방식.. 

여러가지가있는데 오늘은  synchronized를 이용한 방식에 대해 설명할 예정이다.. 

(여러개를 포스팅하고싶지만.. 힘들다 ㅠㅠ 조금이라도 꾸준히 올리는게 목표다)


1.synchronized를 이용한 동기화 


가장 간단한 동기화 방법인 synchronized 키워드를 이용한 동기화에 대해서 알아보면 

이 키워드는 임계 영역을 설정하는데 사용된다. -->두가지 방식이있다. (사진이 생각보다 짱큰게 올라갔다)


<첫 번째 방법>

메서드 앞에 synchronized를 붙이는방법 

synchronized를 붙이면 메서드 전체가 임계영역으로설정된다. 

쓰레드는 synchronized메서드가 호출된 시점부터 해당 메서드가 포함된 객체의 lock을 얻어 작업을 수행한다.

메서드가 종료되면 lock을 반환한다.


<두 번째 방법>

메서드 내의 코드 일부를 블럭 { }으로 감사고 블럭 앞에 'synchronized(참조변수)'를 붙이는 방법

이때 참조변수는 --> 락을 걸고자하는 객체를 참조하는것이어야한다. 


이 {  }블럭을 synchronized블럭이라고 한다. 

->이 블럭의 영역 안으로 들어가면서부터 쓰레드는 지정된 객체의 lock을 얻게되고. 

   블럭을 벗어나면 lock을 반납한다.


-----------

두 방법 모두 lock을 하나씩 가지고 있다.

해당 객체의 lock을 가지고 있는 쓰레드만 임계 영역의 코드를 수행할 수 있다.

그리고 다른 쓰레드들은 lock을 얻을 때가지 기다리게 된다.

------

임계 영역은 멀티쓰레드 프로그램의 성능을 좌우하기 때문에 가능하면 메서드 전체에 락을 거는것보다 

synchronized블럭으로 임계 영역을 최소화해서 효율적인 프로그램이 되도록 노력하는게 좋다.



아래는 synchronized 사용예제에 대해서 설명할거다 


쓰레드 동기화를 사용한 경우와 사용하지 않은 경우의 차이를 간단한 예제를 통해서 설명하려고한다.


공쓰레드와 다일쓰레드가 사용하는 부분을 보여줄 예정이다. 



위에 소스는 

gong과 dile이라는 이름의 스레드를 생성하여 집계판에 동시에 접근하게 한것이다. 

그리고 두 스레드를 실행시키는 부분이다. 


위에 소스와 이어서 타이핑 친부분이다 아래는 

공유 데이터인 집계판을 시물레이션하는 클래스를 만든거다.

이제 아래 소스를 보자 


최종적으로 소스에 흐름에 대해서 설명하자면 


SyncObject멤버 add( )를 synchronized 메소드로 지정했다. 

왜??!

-->add ( )는 두명의 gong,dile 즉 WorkerThread 스레드가 동시에 호출할수있는 임계영역이기 때문이다.

    또한 add( ) 메소드는 sum 공유변수에 접근하고 있기 때문이다. 


WorkerThread는 루프를 돌면서 27번줄에 SyncObject의 add( )메소드를 호출하여 

SyncObject의 sum 멤버 값에 10을 더하고 리턴한다. 

main은 이름이 "gong","dile"인 두개의 WorkerThread 스레드를 생성한다. 


최종 sum이 얼마일꺼같나? ㅋㅋ -->200이다!! 왜??1 

gong와 dile이가 각각 10번씩 add( )를 호출했기때문에 

동기화가 잘이루어진다면 최종 누적점수 sum이 200이 된다. 


그림으로 표현하면 이렇다.. 


어떤 형식으로 찍힐까?

이런식으로 gong과 dile이가 순차적으로 sum되가면서 찍힌다. 


근데 만약에 synchronized키워드를 제거하게 되면 어떻게 출력될까?


실행할때마다 다르긴한데  충돌이된 예시를 보여주자면 


위에 네모박스처럼 add( ) 메소드에 충돌이 생긴경우다

-->이때문에 10이 증가되지못했다.


아래 밑줄처럼 두 스레드의 add(  ) 메소드에 대한 동시 실행으로 인해 190밖에 도달하지 못했다.


근데 저 코드를 맨날 실행한다고 같은 결과가 나오는건 아니다 

여러번 충돌할수도있는거고 충돌안할수도있는거고 하지만 동기화를 해주지 않으면

충돌할 위험이 있기 때문에 해줘야한다. 


두개의 스레드가 동시에 호출할 경우가 발생할 위험이있기때문에 동기화 처리를 해주는거다. 


2.wait( )과 notify( )를 이용한 방식 은 나중에 정리하겠다!! 


:
Posted by Gongdile


-Scanner.nextInt 메소드는 

-->가장 마지막 개행문자(엔터,newline)을 제거하지않는다.


개행문자(엔터)전까지만 숫자로 입력받음.


-->이부분에서 문제가 생김 


nextInt( )와 nextLine( )을 사용시 

넥스트인트에 5를 입력하고 엔터친다고 가정하면

넥스트라인 안에 공백이 입력으로 처리되서 문제가 발생함  


nextLine( )은 한줄을 입력받는다. 


이해를 돕기위해 사진을 첨부하겠다.


이렇게 5입력시에 엔터를 치면 공백이 b안에 들어가서 b가 아무것도 찍히지 않게 된다 


어떻게 해결할꺼냐..?



<1. 중간에 scan.nextLine(  ); 삽입하기>




a와 b입력 사이에 scan.nextLine( )을 하나 넣어서 개행(엔터)를 처리해주는 방법으로 하면


잘출력된다.. 


<2.nextLine( )으로 받아서 parseInt로 변경해서 출력하는 방법>



이 글을 읽는 어떤분중에는..

어그러면 그냥 a를 scan.nextLine( )으로 받음 안됨?! 할수도있을거같은데.. NO!! 



 이런 에러가 친절하게 떠요 ㅎㅎ ! 


--> Line은 String에서 쓸수있습니다. 


Scanner 클래스는 자바에서 제공해주는 클래스인데 

화면, 파일, 문자열과 같은 입력소스로부터 문자데이터 읽어오는데 도움줄 목적으로 추가된거에요. 


자세한 설명은 생략하고 Scanner사용시에는 데이터 형식에 맞는 메서드를 사용해줘야합니다.. 

이건 표로 정리하겠습니다.


[표 - 데이터형식과 Scanner메서드]


 

 형식

메소드 
 논리형

boolean (

nextBoolean( ) 

 정수형

byte 

nextByte( ) 

short 

nextShort( ) 

int 

nextInt( ) 

long 

nextLong( ) 

 실수형

double 

nextDouble( ) 

float 

nextFloat( ) 

 문자

String 

next( ) //띄어쓰기로 구분

nextLine(  ) // 한 문장 전체, 엔터키로 구분



맞게 사용하시면 되요.. 


<3. 스캐너를 두개받는 방법>



스캐너를 사용하는 방법이다..


개인적으로는 그냥 중간에 Scan.nextLine( )삽입하는게 제일 편하다고 생각한다.! 


정리하는데 은근 시간을 많이.. 무튼 정리 끝!



:
Posted by Gongdile