Synchronized로 검색한 결과 :: 시소커뮤니티[SSISO Community]
 
SSISO 카페 SSISO Source SSISO 구직 SSISO 쇼핑몰 SSISO 맛집
추천검색어 : JUnit   Log4j   ajax   spring   struts   struts-config.xml   Synchronized   책정보   Ajax 마스터하기   우측부분

회원가입 I 비밀번호 찾기


SSISO Community검색
SSISO Community메뉴
[카페목록보기]
[블로그등록하기]  
[블로그리스트]  
SSISO Community카페
블로그 카테고리
정치 경제
문화 칼럼
비디오게임 스포츠
핫이슈 TV
포토 온라인게임
PC게임 에뮬게임
라이프 사람들
유머 만화애니
방송 1
1 1
1 1
1 1
1 1
1

Synchronized로 검색한 결과
등록일:2009-07-23 17:18:13
작성자:
제목:public static syncronized void


출처

http://javaservice.net/~java/bbs/read.cgi?m=qna&b=qna2&c=r_p_p&n=1011915622

 

 

묻고 답하기
제목 : static 관련한 질문입니다. 고수님들 부탁합니다.
글쓴이: 손님(guest) 2002/01/25 07:10:57 조회수:248 줄수:46
[프린트]
안녕하세요.
static으로 선언한 변수나 메소드에 대해서 질문이 있습니다.

jsp와 Bean(DB핸들링 작업)을 연동해서 프로젝트를 개발하고 있습니다.
제가 투입된것은 프로젝트 마무리 단계여서 수정을 위주로 하고 있습니다.

소스중에....
현재 년도, 현재 날짜, 현재 시간등을 얻어온다던가.. 
금액 등을 나타내는 숫자에 천단위 구분자를 넣는다던가..
문자열에서 특정 문자열을 다른 문자열로 대체한다던가..
이외의 여러가지 자주 사용되는 공통적인 작업들을 모아놓은 Util 클래스가 있는데요..

모든 메소드며 변수가 static으로 선언이 되어 있구요..
특히 모든 메소드에는 Synchronized 가 선언이 되어 있습니다.
위에 말씀드린 작업을 수행하는데 굳이 동기화가 필요하진 않을 것 같아
Synchronized 를 빼려고 하는데요..
갑자기 static이라는 개념자체가 흔들리면서 저를 괴롭히네요..

변수에 static을 선언하면..
이 변수를 사용하는 모든 객체들이 이 변수를 공유하는 것으로 알고 있습니다.
어떤 객체가 이 변수를 값을 바꾸면..
이후에 접근하는 다른 객체들은 바뀐값을 적용받게 되겠지요.

그럼 메소드의 경우는 어떠한가요..
메소드 안에서 로컬변수를 선언한다던가..
인자로 어떤 값을 받아서(이것도 로컬변수 입니다만..) 작업을 하는 메소드라면..
예를 들어... 
인자로 int a 와 int b 를 받아서 이들의 합을 리턴하는 메소드가 있다고 가정할 때..
두 객체가 동시에 이 메소드에 접근을 한다면 어떤 현상이 일어나는 것입니까?..

메소드에 static을 선언한다는 것은 어떤 의미입니까..
메소드가 static이면 그 안에서 선언된 로컬 변수까지도 공유가 되는 것입니까?
아니면..메소드에 정의되어 있는 코드만을 별도의 객체생성없이 사용할 수 있다는 의미입니까..

그리고...
일반적인 인스턴스 메소드에 Synchronized 을 선언하면...
그 메소드를 실행하기 위해서는 그 객체의 lock flag를 얻어야 하는 것으로 알고 있습니다.
static에 Synchronized을 선언하면...lock flag는 누구의 lock flag가 되는 것입니까..

자바로 개발을 일년이나 했다는 사람이..
이 정도 개념도 없다니 너무 부끄럽습니다.
많은 고수님들의 조언을 부탁드립니다.



제목 : Re: static 관련한 질문입니다. 고수님들 부탁합니다.
글쓴이: 손님(guest) 2002/01/25 08:40:22 조회수:304 줄수:92
> 메소드에 static을 선언한다는 것은 어떤 의미입니까..
> 메소드가 static이면 그 안에서 선언된 로컬 변수까지도 공유가 되는 것입니까?
> 아니면..메소드에 정의되어 있는 코드만을 별도의 객체생성없이 사용할 수 있다는 의미입니까..

저도 자바를 많이 하진 않았지만, 제가 생각하는 걸 말씀드립니다.
class A{
  public syncronized void a(){....}
  public static syncronized void b(){....}
}

이 둘의 차이점을 알아보믄.
syncronized는 모두 메소드에 락을 거는 것입니다.

객체 A를 한번만 new() 시킨다면, 객체 A 한개가 생성될 것입니다.

그런다음 프로그램 상에서 여러개의 쓰레드를 발생시켜서 

A.a()함수를 call하게 하면, 어느 한 쓰레드가 a()를 점령하고 있는 동안 a()를 

쓸 수 없겠져.. 

그런데, 객체 A를 두번 new() 시켰다고 합시다. 객체가 두개 발생한 시점입니다.

편의상 가, 나 객체라 합시다.

그런다음 프로그램상에서 여러개의 쓰레드를 발생시켜서,

a()와 b()를 호출하게 되면, a()가 락걸리는 것은 스테틱이 아니므로

'가'객체 쓰레드끼리만 a()함수에 락이 걸리고 '나'객체 쓰레드는 락이 안걸립니다.

반면에, b()함수는 스테틱이므로 모든 A객체에 대해 sync됩니다. 즉

'가'객체의 쓰레드가 b()를 호출하는 동안 '나'객체쓰레드도 b()에 락이 걸립니다.


저는 스테틱이란것을 메모리공유란 의미로 생각합니다.

변수를 스테틱 선언하면 클래스 원형(prototype)에 변수공간이 생기고,

객체가 힙에 생기게 되면, 스태틱 멤버변수의 자리는 변수저장공간이 있는 것이 아니고,

클래스 원형의 변수공간을 가리키는 주소가 들어있습니다.

그래서 객체의 값을 바꾸게 되면, 실제로 클래스원형의 변수를 바꾸게 되므로,

모든 객체의 값을 바꾸게 되는 거지요..


메소드의 경우는 약간 다릅니다.

객체가 힙에 생기게 되면, 변수는 저장공간이 생기게 되나, 코드(메소드)는 공유합니다.

공유되는 코드영역은 클래스원형(prototype)공간에 존재하며, 

객체는 이 메소드의 시작위치를 가리키는 주소변수를 가지고 있습니다.

모든 객체의 특정(A)메소드를 호출하면, 같은 코드를 사용하는 겁니다..

그런데 메소드 호출을 하면, 클래스원형 것을 사용하는 게 아니고,

그 메소드 코드부분을 스택영역에 복사한다음에 사용합니다.

그런데 syncronized가 걸려있으면, 여러개의 쓰레드가 그 메소드를 동시에 

사용하지 못한다는 것이죠..


아까 스태틱은 메모리공유란 의미라고 했죠..

스태틱이라고 되어있으면, 그 메소드 코드는 스택에 복사해서 쓰지않고,

클래스원형의 메소드코드영역에서 공유되어 실행됩니다.

그래서 syncronized가 되어있으면, 객체가 여러개일때, 쓰레드를 여러개 생겨도,

한 객체에서 그 메소드를 쓰고있는 동안에는 모든 객체가 락이 걸려 사용할 수 

없습니다.


저도 자바한지 일년정도 밖에 안되서 내용이 틀릴 수도 있습니다.

제가 생각하는 방식은 그런 겁니다. 책에서 나온 내용을 나름대로 생각한 것인데,

실제로 메모리상에서 그렇게 되는지는 모르겠습니다.

하지만, 그런 생각으로 접근을 하니 이해는 잘 되는 거 같더군요..

   
제목 : Re: static 관련한 질문입니다. 고수님들 부탁합니다.
글쓴이: 질문한사람(guest) 2002/01/25 09:51:33 조회수:178 줄수:61
> 아까 스태틱은 메모리공유란 의미라고 했죠..
> 
> 스태틱이라고 되어있으면, 그 메소드 코드는 스택에 복사해서 쓰지않고,
> 
> 클래스원형의 메소드코드영역에서 공유되어 실행됩니다.
> 
> 그래서 syncronized가 되어있으면, 객체가 여러개일때, 쓰레드를 여러개 생겨도,
> 
> 한 객체에서 그 메소드를 쓰고있는 동안에는 모든 객체가 락이 걸려 사용할 수 
> 
> 없습니다.


답변 감사합니다.. (-.-)(_._)(-.-)....

지식이라는 것이 알고는 있어도 남에게 설명하자면 힘든 것인데..
비슷한 경력을 가지신 분께서 확실한 개념을 잡고 계신 걸 보니...
나태했던 제 자신이 너무 부끄럽습니다.
덕분에 앞으로 자바를 개념부터 다시 공부해야 겠다는 마음을 먹게 되었습니다.
다시 한번 감사드립니다.

답변해주신 내용에 대해서 궁금한 것이 있는데요..
메소드에 syncronized 없이 static으로만 선언되어 있는 경우를 생각할 때...

> 스태틱이라고 되어있으면, 그 메소드 코드는 스택에 복사해서 쓰지않고, 
> 클래스원형의 메소드코드영역에서 공유되어 실행됩니다.

라고 하셨습니다.

질문에도 같은 내용이 있습니다만..

메소드 안에서 로컬변수를 선언한다던가..
인자로 어떤 값을 받아서 작업을 하는 메소드라면..
예를 들어... 
인자로 a 와 b 를 받아서 이들의 합을 리턴하는 메소드 static으로 선언되었을 때..
이 메소드가 구현되어 있는 클래스를 Util클래스이구요..
jsp에서 주로 이 메소드들을 호출하여 사용합니다.
 
이런 상황에서 두 명이 동시에 같은 jsp를 호출했다고 가정합니다.
두 개의 스레드가 생길거구요..
이 두 스레드가 동시에 이 메소드에 접근을 한다면 어떤 현상이 일어나는 것입니까?..

그러니까.. 스레드A가 1 , 2 를 인자로 주고 이들의 합을 구하려는 시점에..
스레드B가 접근해서 인자를 4, 5로 주었다고 가정한다면..

스레드 A는 원하지도 않는 값을 리턴받게 되는 것입니까?
그러니까..로컬변수까지도 공유하게 되는가 하는 질문입니다.

만약 그렇다면...웹 환경에서..
공통적으로 사용하는 작업들만 모아놓은 Util클래스에서 
메소드에 static을 사용한다면..반드시 동기화를 시켜야 한다는 결론이 됩니다..

이런 해석이 맞는 것인지...궁금합니다..

다시 한번 고견을 부탁드립니다.





제목 : Re: static 관련한 질문입니다. 고수님들 부탁합니다.
글쓴이: 김민호(minotech) 2002/01/25 10:55:21 조회수:205 줄수:85
>  
> 이런 상황에서 두 명이 동시에 같은 jsp를 호출했다고 가정합니다.
> 두 개의 스레드가 생길거구요..
> 이 두 스레드가 동시에 이 메소드에 접근을 한다면 어떤 현상이 일어나는 것입니까?..
> 
> 그러니까.. 스레드A가 1 , 2 를 인자로 주고 이들의 합을 구하려는 시점에..
> 스레드B가 접근해서 인자를 4, 5로 주었다고 가정한다면..
> 
> 스레드 A는 원하지도 않는 값을 리턴받게 되는 것입니까?
> 그러니까..로컬변수까지도 공유하게 되는가 하는 질문입니다.


결론을 먼저 말하면, 걱정할 필요없다 입니다.


제가 설명중에 메소드 메모리 영역에서 같은 영역이라고 했는데,

실제로는 엄밀히 말하믄, 그렇지는 않은 것 같습니다.

왜냐하면,

methodA(int i){
  .......
 i++;
 while(true){
 methodA();
 if (i > 10){
   break;
 }
}


재귀적으로 호출하는 함수입니다. 같은 메모리 영역일텐데,

i라는 변수영역에 있는 값이 달라지면, 문제가 생기겠죠?

처음 들어갔을 때의 i의 값과 두번째 들어갔을때의 i값은 분명이 다를 것입니다.

분명 저장하는 장소가 있을텐데, 아마, 스택이라는 영역에 둘 것입니다.

코드영역은 쓰기가 금지된 구간입니다.(제생각임)

로컬변수때문에 모든 코드를 다시복사한다면, 리소스 낭비가 너무 클 것입니다. 

코드는 하나일 것입니다.코드들 스택에 저장한다구 했는데, 실제로는 모든 코드가

복사되는 것이 아니라(그럴 필요도 없음), 로컬변수값과 

IP(Instruction Pointer 코드영역내의 위치, 즉 어디를 실행중인가하는 위치)

값만 복사된다고 생각합시다(그것만 있음 쓰레드가 실행됐을때 원위치로 찾아갑니다).

그러면 로컬 변수는 따로 저장을 해야하고, 바로 스택에 저장됩니다.

만약 같은 메소드를 10개의 쓰레드가 공유했을때 특정순간에,

모두 메소드내에서 실행중이라면, 10개의 로컬변수와 IP가 생길 것입니다.

그러므로 서로 헷갈릴 염려는 없겠지요..

그런데 만약 로컬변수도 스태틱이라면 메모리 공유이므로, 

헷갈릴 가능성도 있을것 같습니다.

설명이 되었는지 모르겠네여..


부가적으로 말씀드리면, 위와 같은 이유때문에

객체의 멤버변수는 초기화를 안해도 메모리 공간을 가지기 때문에 초기화가 되지만,

배열도 마찬가지임(메모리 공간을 가지면 초기화됨)

로컬변수는 필요시에만, 메모리 공간을 순간순간 갖기 때문에 

(코드영역내에서 저장되지 않음)초기화를 안하면, 컴파일 에러가 납니다.




 



제목 : Re: 동기화문제 걱정없이 사용하셔도 괜찮습니다
글쓴이: 진헌규(redblade) 2002/01/26 00:41:22 조회수:327 줄수:155
제 나름대로 답변을 드리자면 아래와 같습니다.

> 메소드에 static을 선언한다는 것은 어떤 의미입니까..
> 메소드가 static이면 그 안에서 선언된 로컬 변수까지도 공유가 되는 것입니까?
> 아니면..메소드에 정의되어 있는 코드만을 별도의 객체생성없이 사용할 수 있다는 의미입니까..

님이 써놓으셨던 것처럼 '메소드에 정의되어 있는 코드를 별도의 객체생성없이 
사용할 수 있다'는 의미입니다. 유틸리티 클래스에 딸려있는 메쏘드는 거의 대부분
static이죠.

그리고 로컬 변수(java에서는 automatic variable이라는 표현을 씁니다만... 어쨌든
메쏘드 내부에서만 사용되는 변수죠)는, runtime stack에 저장되는 것으로 알고 있습니다.
그리고 runtime stack은 Thread마다 하나씩 갖게 되구요.

따라서 static 메쏘드 내에서 선언된 automatic variable의 경우는 100% thred-safe합니다.
(사실 static 메쏘드가 아니더라도 그렇습니다. static이든 아니든 어차피 그 변수값들이
저장되는 영역은 해당 class와 전혀 무관한, runtime stack일테니까요)

> 
> 그리고...
> 일반적인 인스턴스 메소드에 Synchronized 을 선언하면...
> 그 메소드를 실행하기 위해서는 그 객체의 lock flag를 얻어야 하는 것으로 알고 있습니다.
> static에 Synchronized을 선언하면...lock flag는 누구의 lock flag가 되는 것입니까..
> 

lock의 타입에는 두가지가 있습니다. 인스턴스 락과 클래스 락이 있구요, 
인스턴스 락은 다음과 같은 경우에 사용됩니다.

1) static이 아닌 메쏘드에 Synchronized를 붙였을 때 (자체 인스턴스의 락을 사용)

-> Synchronized public void syncTest()같은 경우겠죠.

2) 특정 인스턴스에 대해 Synchronized를 붙였을 때

Object lock = new Object();
Synchronized (lock)
{
    nonSynchronizedMethod();
}
-> 위와 같은 경우입니다. 사실 1)번의 경우는 JVM이 알아서 Synchronized (this)를
해주는 것과 동일합니다.

그리고 클래스 락은 다음과 같은 경우에 사용됩니다.

1) static 메쏘드에 Synchronized를 붙였을 때 (자체 클래스의 락을 사용)

-> Synchronized public static void syncStaticTest()같은 경우겠죠.

2) 특정 클래스에 대해 Synchronized를 붙였을 때

Object lock = new Object();
Synchronized (lock.getClass())
{
    nonSynchronizedMethod();
}
-> 위와 같은 경우입니다. 사실 1)번의 경우는 JVM이 알아서 Synchronized (getClass())를
해주는 것과 동일합니다.

이제 그럼 인스턴스 락과 클래스 락의 차이에 대해 말씀드리면 되겠네요.

인스턴스 락의 범위는 개별 인스턴스로 '제한'됩니다. 가령, 같은 SyncTest 클래스의
두 인스턴스 a, b가 있는데 a.SynchronizedMethod()와 b.SynchronizedMethod()는 서로
아무런 영향없이 독립적으로 수행됩니다.

사실, 인스턴스 락의 범위는 개별 인스턴스 '그 자체'입니다. 클래스 하나에
Synchronized 메쏘드가 2개라고 한다면, 같은 인스턴스에 대해 두 메쏘드를 동시에
호출할 수 없습니다. 즉, Synchronized는 메쏘드 단위 락이 아니라 인스턴스 단위의
락입니다. (테스트해보실 수 있는 코드를 뒤에 첨부하겠습니다)

그리고, 클래스 락은 위에서 보셨듯이, 특정 인스턴스의 클래스에 대해 걸리는
락입니다. (Synchronized (obj.getClass()) 부분을 생각하세요) 

그리고, 가장 중요한 것으로, 인스턴스 락과 클래스 락은 서로 '겹치지 않습니다'.
즉, 그냥 Synchronized 메쏘드와 static Synchronized 메쏘드는 동시에 호출될 수
있습니다. 아예 "락에는 두 종류가 있고, 서로 다르다"고 생각하시는게 맞을 겁니다.


마지막으로 님께서 궁금해하셨던 문제에 대해 결론을 말씀드린다면,
유틸리티 클래스의 static 메쏘드 내부에서 사용되는 automatic variable들의 
경우, 100% thread-safe하므로 Synchronized 키워드를 사용하지 않으셔도 좋다는 것입니다.


아래에 동기화 여부를 테스트해볼 수 있는 간단한 소스를 첨부합니다.
제가 주석처리해둔 부분에서 method1, method2, smethod1, smethod2를 적절히
섞어서 넣어주시면 인스턴스 락과 클래스 락이 작동하는 방식에 대해 확인하실
수 있을 겁니다.

1 public class SyncTest 2 { 3 Synchronized public void method1() 4 { 5 System.out.println("method1()"); 6 sleep(); 7 }; 8 9 Synchronized public void method2() 10 { 11 System.out.println("method2()"); 12 sleep(); 13 }; 14 15 static Synchronized public void smethod1() 16 { 17 System.out.println("smethod1()"); 18 sleep(); 19 }; 20 21 static Synchronized public void smethod2() 22 { 23 System.out.println("smethod2()"); 24 sleep(); 25 }; 26 27 static void sleep() 28 { 29 try 30 { 31 Thread.sleep(1000); 32 } 33 catch (InterruptedException ex) 34 { 35 } 36 } 37 38 public static void main(String[] args) 39 { 40 final SyncTest s = new SyncTest(); 41 42 Thread t1 = new Thread() 43 { 44 public void run() 45 { 46 System.out.println("beginning method1"); 47 s.method1(); //--> 이 부분을 선택하세요. 48 System.out.println("method1 finished"); 49 } 50 }; 51 t1.start(); 52 53 Thread t2 = new Thread() 54 { 55 public void run() 56 { 57 System.out.println("beginning method2"); 58 smethod1(); //--> 이 부분을 선택하세요. 59 System.out.println("method2 finished"); 60 } 61 }; 62 t2.start(); 63 } 64 }
제목 : 답변 정말 너무나 감사합니다. (내용 무..)
글쓴이: 질문한사람(guest) 2002/01/27 03:48:18 조회수:66 줄수:1
...