SICP<br />3.4  Concurrency:Time Is of the Essence병행성: 시간은 중요하다<br />http://ohyecloudy.com<br />http://cafe.naver.com/archi...
덮어쓰기 연산<br />물체에 상태를 부여<br />계산 방법에 시간 개념 추가<br />만약 없다면 시간의 영향을 받지 않고 한결같아 진다.<br />(withdraw25)<br />75<br />(withdraw25...
병행 시스템에서 시간의 본질<br />(define(withdrawamount)<br />(if(&gt;=balance amount)<br />(begin(set!balance (-balance amount))<br /...
병행 프로그램의 올바른 동작<br />변수 하나에 여러 프로세스가 값을 덮어쓰려고 하는게 문제를 복잡하게 하고 있다.<br />상태 변화가 병행으로 일어날 때 예측 가능하게 동작하도록 병행 처리에 제약을 준다.<br />
병행 처리에 제약을 주는 방법<br />상태 변수 하나를 같이 사용<br />값을 바꿀 수 있는 연산 두 개가 동시에 돌아가지 못하게 제약<br />차례대로 돌아가게 만들어 병행 프로그램과 같은 결과를 만들어 낸다.<b...
병행 프로세스를 다루기 어려운 까닭<br />여러 프로세스에서 일어나는 사건의 차례가 서로 뒤엉킬 수 있기 때문<br />모든 경우를 하나하나 따져봐야 한다.<br />사건이 많아질수록 경우의 수가 폭발적으로 증가한다....
parallel-execute<br />(definex 10)<br />(parallel-execute(lambda()(set!x (*x x))); P1<br />(lambda()(set!x (+x 1)))); P2<b...
병행성을 다스리는 방법<br />서로 뒤엉켜 돌아가는 여러 프로세스에 어떤 제약을 걸어서, 프로그램이 제대로 돌아간다고 믿을 수 있도록 병행 시스템을 설계하는 방법이 필요하다.<br />줄 세우개(serializer)가...
줄 세우개(serializer)<br />병행으로 돌아가지 못하는 프로시저를 정의<br />여러 프로세스가 함께 쓰는 변수를 다스릴 수 있다.<br />
make-serializer<br />(definex 10)<br />(defines (make-serializer))<br />(parallel-execute(s(lambda()(set!x (*x x)))); P1<b...
줄 세우개를 사용한 은행 계정<br />잔액을 변경하는 withdraw, deposit 프로시저를 같은 줄 세우개를 사용해 동시에 실행할 수 없게 제한했다.<br />줄 세우개는 계정마다 하나씩 가진다.<br />서로 ...
(define(make-accountbalance)<br />(define(withdrawamount)<br />(if(&gt;=balance amount)<br />(begin(set!balance (-balance ...
연습 3.41<br />balance에 손을 댈 때 줄 세우기를 하지 않으면 제대로 돌아가지 않을 수도 있다는데 동의?<br />(define(make-accountbalance)<br />(define(withdraw...
연습 3.41 풀이<br />줄 세우기를 한 결과 withdraw, deposit과 balance는 동시에 실행되지 않는다.<br />balance는 값을 변경하는 동작이 아니라 값을 읽는 동작을 하는 프로시저.<br ...
연습 3.42<br />이렇게 만들어도 괜찮은가? 변경 전 make-account와 병행성에 어떤 차이가 나는가?<br />(define(make-accountbalance)<br />(define(withdrawamo...
연습 3.42 풀이<br />상관 없다.<br />이전과 상관없이 make-serializer는 은행 계정 하나당 하나가 존재한다.<br />make-serializer프로시저를 실행하는 프로시저를 미리 만들어서 같은 ...
여러 자원을 함께 쓰는 문제<br />이제 까지 자원 하나를 여럿이 쓰는 예제.<br />폴과피터가 같이 쓰는 생활비 은행 계좌<br />여러 자원을 함께 쓰는 경우를 살펴보자.<br />두 은행 계정의 남은 돈을 맞바...
exchange<br />(define(exchangeaccount1 account2)<br />(let((difference(-(account1&apos;balance)<br />(account2&apos;balanc...
해결 방법<br />두 계정의 줄 세우개를 사용해 exchange 프로시저 전체를 줄 세운 프로시저로 만든다.<br />계정 속의 줄 세우개를 밖으로 노출 시켜야 한다.<br />모듈 방식이 깨짐<br />현재로선 다른...
(define(make-account-and-serializerbalance)<br />(define(withdrawamount)<br />(if(&gt;=balance amount)<br />(begin(set!bal...
serialized-exchange<br />(define(serialized-exchangeaccount1 account2)<br />(let((serializer1(account1&apos;serializer))<b...
연습문제 3.44<br />돈을 맞바꾸는 문제처럼 transfer 프로시저 자체를 줄 세운 프로시저로 만들어야 하는가?<br />(define(transferfrom-account to-account amount)<br...
연습문제 3.44 풀이<br />필요 없다.<br />돈을 맞바꾸는 경우에는 두 은행 계정의 남은 돈의 차이를 계산한 후에 인터럽트가 걸린 경우 두 은행 계정의 남은 돈 차이가 변할 수 있기 때문에 돈을 맞바꾸는 프로시...
연습문제 3.45<br />serialized-exchange를 불러 쓸 때 어떤 일이 일어나는지 따져라<br />(define(make-account-and-serializerbalance)<br />(define(w...
연습문제 3.45 풀이<br />serialized-exchange 프로시저는 두 계정의 줄 세우개로 프로시저 전체를 줄 세운 프로시저로 만든다.<br />안에서 exchange 프로시저를 실행하는데, withdraw,...
make-serializer구현<br />뮤텍스(mutex)<br />mutual exclusion : 상호 배제<br />뮤텍스 물체를 쥐거나(acquired) 풀어 주는(release) 연산<br />한 프로세스가 ...
(define(make-serializer)<br />(let((mutex(make-mutex)))<br />(lambda(p)<br />(define(serialized-p.args)<br />(mutex&apos;a...
test-and-set! 구현<br />(define(test-and-set!cell)<br />(if(carcell)<br />true<br />(begin(set-car!cell true)<br />false)))<...
연습문제 3.47<br />세마포어(semaphore)를 뮤텍스와test-and-set!을 써서 만들어라.<br /><ul><li> 잡았다 놓았다 하는 연산은 뮤텍스와 같지만 n개 프로세스가 병행으로 세마포어를 쥘 수 있다.
뮤텍스를 사용하는 것만 풀이</li></li></ul><li>연습문제 3.47 풀이<br />(define(new-make-semaphoren)<br />(let((count0)<br />(mutex(make-mutex...
데드락(deadlock)<br />여러 프로세스가 다른 프로세스를 지켜보면서 아무것도 하지 못하고 끝없이 기다려야 하는 상태<br />돈 맞바꾸는 문제의 경우에는 계정마다 번호를 매겨 놓고 모든 프로세스가 언제나 번호가...
연습문제 3.48<br />계정에 번호를 매겨, 각 프로세스가 처음에 더 작은 번호를 매긴 계정을 움켜쥐도록 만들어서 데드락을 피하는 기법을 사용.<br />왜 돈 맞바꾸는 문제에서 데드락에 빠지지 않는가?<br />그...
연습문제 3.48 풀이<br />(define(make-account-and-serializerid balance)<br />(define(withdrawamount)<br />(if(&gt;=balance amount...
연습문제 3.48 풀이(계속)<br />(define(serialized-exchangeaccount1 account2)<br />(let((serializer1(account1&apos;serializer))<br /...
끝<br />
Upcoming SlideShare
Loading in …5
×

[SICP] 3.4 Concurrency : Time is of the essence - 병행성 : 시간은 중요하다.

1,834 views
1,733 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,834
On SlideShare
0
From Embeds
0
Number of Embeds
395
Actions
Shares
0
Downloads
3
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

[SICP] 3.4 Concurrency : Time is of the essence - 병행성 : 시간은 중요하다.

  1. 1. SICP<br />3.4 Concurrency:Time Is of the Essence병행성: 시간은 중요하다<br />http://ohyecloudy.com<br />http://cafe.naver.com/architect1.cafe<br />
  2. 2. 덮어쓰기 연산<br />물체에 상태를 부여<br />계산 방법에 시간 개념 추가<br />만약 없다면 시간의 영향을 받지 않고 한결같아 진다.<br />(withdraw25)<br />75<br />(withdraw25)<br />50<br />
  3. 3. 병행 시스템에서 시간의 본질<br />(define(withdrawamount)<br />(if(&gt;=balance amount)<br />(begin(set!balance (-balance amount))<br />balance)<br />&quot;Insufficient funds&quot;))<br />100<br />잔액 조회 : 100<br />잔액 조회 : 100<br />새 값 : 100 – 10 = 90<br />새 값 : 100 – 25 = 75<br />90<br />잔액을 90으로 set!<br />잔액을 75로 set!<br />75<br />
  4. 4. 병행 프로그램의 올바른 동작<br />변수 하나에 여러 프로세스가 값을 덮어쓰려고 하는게 문제를 복잡하게 하고 있다.<br />상태 변화가 병행으로 일어날 때 예측 가능하게 동작하도록 병행 처리에 제약을 준다.<br />
  5. 5. 병행 처리에 제약을 주는 방법<br />상태 변수 하나를 같이 사용<br />값을 바꿀 수 있는 연산 두 개가 동시에 돌아가지 못하게 제약<br />차례대로 돌아가게 만들어 병행 프로그램과 같은 결과를 만들어 낸다.<br />어떤 차례인지 결정하지 않으면 올바른 결과가 여러 개다.<br />열의 퍼짐 시뮬레이션(flow of heat in an object)<br />여러 개의 프로세스<br />자기 값과 이웃 값의 평균으로 자기 값 수정<br />되풀이 하다보면 올바른 값으로 수렴<br />
  6. 6. 병행 프로세스를 다루기 어려운 까닭<br />여러 프로세스에서 일어나는 사건의 차례가 서로 뒤엉킬 수 있기 때문<br />모든 경우를 하나하나 따져봐야 한다.<br />사건이 많아질수록 경우의 수가 폭발적으로 증가한다.<br />(a,b,c,d,e,f) 사건이 차례대로 일어나는 A 프로세스와 (x,y,z,w) 사건이 차례대로 일어나는 B 프로세스가 있다면???<br />
  7. 7. parallel-execute<br />(definex 10)<br />(parallel-execute(lambda()(set!x (*x x))); P1<br />(lambda()(set!x (+x 1)))); P2<br />P1 : a (첫 번째 x 읽기), b (두 번째 x 읽기), c (x를 덮어쓰기)<br />P2 : ㄱ(x 읽기), ㄴ(x를 덮어쓰기)<br />두 프로세스가 끝난 다음 나올 수 있는 x의 값<br />101 : a  b  c  ㄱ ㄴ<br />121 : ㄱ ㄴ a b c<br />110 : a  ㄱ ㄴ b  c<br />11 : ㄱ a  b  c  ㄴ<br />100 : a  b  ㄱ ㄴ c<br />
  8. 8. 병행성을 다스리는 방법<br />서로 뒤엉켜 돌아가는 여러 프로세스에 어떤 제약을 걸어서, 프로그램이 제대로 돌아간다고 믿을 수 있도록 병행 시스템을 설계하는 방법이 필요하다.<br />줄 세우개(serializer)가 한가지 방법.<br />
  9. 9. 줄 세우개(serializer)<br />병행으로 돌아가지 못하는 프로시저를 정의<br />여러 프로세스가 함께 쓰는 변수를 다스릴 수 있다.<br />
  10. 10. make-serializer<br />(definex 10)<br />(defines (make-serializer))<br />(parallel-execute(s(lambda()(set!x (*x x)))); P1<br />(s(lambda()(set!x (+x 1))))); P2<br />P1 : a (첫 번째 x 읽기), b (두 번째 x 읽기), c (x를 덮어쓰기)<br />P2 : ㄱ(x 읽기), ㄴ(x를 덮어쓰기)<br />두 프로세스가 끝난 다음 나올 수 있는 x의 값<br />101 : a  b  c  ㄱ ㄴ<br />121 : ㄱ ㄴ a b c<br />110 : a  ㄱ ㄴ b  c<br />11 : ㄱ a  b  c  ㄴ<br />100 : a  b  ㄱ ㄴ c<br />
  11. 11. 줄 세우개를 사용한 은행 계정<br />잔액을 변경하는 withdraw, deposit 프로시저를 같은 줄 세우개를 사용해 동시에 실행할 수 없게 제한했다.<br />줄 세우개는 계정마다 하나씩 가진다.<br />서로 다른 계정의 작업은 병행으로 이루어진다.<br />
  12. 12. (define(make-accountbalance)<br />(define(withdrawamount)<br />(if(&gt;=balance amount)<br />(begin(set!balance (-balance amount))<br />balance)<br />&quot;Insufficient funds&quot;))<br />(define(depositamount)<br />(set!balance (+balance amount))<br />balance)<br />(let((protected(make-serializer)))<br />(define(dispatchm)<br />(cond((eq?m &apos;withdraw)(protectedwithdraw))<br />((eq?m &apos;deposit)(protecteddeposit))<br />((eq?m &apos;balance)balance)<br />(else(error&quot;Unknown request -- MAKE-ACCOUNT&quot;m))))<br />dispatch))<br />
  13. 13. 연습 3.41<br />balance에 손을 댈 때 줄 세우기를 하지 않으면 제대로 돌아가지 않을 수도 있다는데 동의?<br />(define(make-accountbalance)<br />(define(withdrawamount)<br />(if(&gt;=balance amount)<br />(begin(set!balance (-balance amount))<br />balance)<br />&quot;Insufficient funds&quot;))<br />(define(depositamount)<br />(set!balance (+balance amount))<br />balance)<br />(let((protected(make-serializer)))<br />(define(dispatchm)<br />(cond((eq?m &apos;withdraw)(protectedwithdraw))<br />((eq?m &apos;deposit)(protecteddeposit))<br />((eq?m &apos;balance)<br />((protected(lambda()balance)))); serialized<br />(else(error&quot;Unknown request -- MAKE-ACCOUNT&quot;m))))<br />dispatch))<br />
  14. 14. 연습 3.41 풀이<br />줄 세우기를 한 결과 withdraw, deposit과 balance는 동시에 실행되지 않는다.<br />balance는 값을 변경하는 동작이 아니라 값을 읽는 동작을 하는 프로시저.<br />Ben은 balance를 거래 후 잔액으로 생각.<br />동의하지 않음.<br />balance프로시저를 실행하는 그 시간에 잔액을 보여줘야 한다고 생각한다.<br />
  15. 15. 연습 3.42<br />이렇게 만들어도 괜찮은가? 변경 전 make-account와 병행성에 어떤 차이가 나는가?<br />(define(make-accountbalance)<br />(define(withdrawamount)<br />(if(&gt;=balance amount)<br />(begin(set!balance (-balance amount))<br />balance)<br />&quot;Insufficient funds&quot;))<br />(define(depositamount)<br />(set!balance (+balance amount))<br />balance)<br />(let((protected(make-serializer)))<br />(let((protected-withdraw(protectedwithdraw))<br />(protected-deposit(protecteddeposit)))<br />(define(dispatchm)<br />(cond((eq?m &apos;withdraw)protected-withdraw)<br />((eq?m &apos;deposit)protected-deposit)<br />((eq?m &apos;balance)balance)<br />(else(error&quot;Unknown request -- MAKE-ACCOUNT&quot;m))))<br />dispatch)))<br />
  16. 16. 연습 3.42 풀이<br />상관 없다.<br />이전과 상관없이 make-serializer는 은행 계정 하나당 하나가 존재한다.<br />make-serializer프로시저를 실행하는 프로시저를 미리 만들어서 같은 프로시저를 내놓는다고 하더라도 줄 세운 프로시저가 같이 쓰는 뮤텍스와 같은 동기화 수단에 의존하기 때문<br />그렇기 때문에 병행성 또한 차이가 없다.<br />뒤에 make-serializer구현 참조.<br />
  17. 17. 여러 자원을 함께 쓰는 문제<br />이제 까지 자원 하나를 여럿이 쓰는 예제.<br />폴과피터가 같이 쓰는 생활비 은행 계좌<br />여러 자원을 함께 쓰는 경우를 살펴보자.<br />두 은행 계정의 남은 돈을 맞바꾸는 일.<br />
  18. 18. exchange<br />(define(exchangeaccount1 account2)<br />(let((difference(-(account1&apos;balance)<br />(account2&apos;balance))))<br />((account1&apos;withdraw)difference)<br />((account2&apos;deposit)difference)))<br />difference 변수에 값을 할당 후 withdraw, deposit 프로시저 호출 전에 account1, account2의 balance가 변경될 수 있다.<br />
  19. 19. 해결 방법<br />두 계정의 줄 세우개를 사용해 exchange 프로시저 전체를 줄 세운 프로시저로 만든다.<br />계정 속의 줄 세우개를 밖으로 노출 시켜야 한다.<br />모듈 방식이 깨짐<br />현재로선 다른 방법이 없다.<br />
  20. 20. (define(make-account-and-serializerbalance)<br />(define(withdrawamount)<br />(if(&gt;=balance amount)<br />(begin(set!balance (-balance amount))<br />balance)<br />&quot;Insufficient funds&quot;))<br />(define(depositamount)<br />(set!balance (+balance amount))<br />balance)<br />(let((balance-serializer(make-serializer)))<br />(define(dispatchm)<br />(cond((eq?m &apos;withdraw)withdraw)<br />((eq?m &apos;deposit)deposit)<br />((eq?m &apos;balance)balance)<br />((eq?m &apos;serializer)balance-serializer)<br />(else(error&quot;Unknown request -- MAKE-ACCOUNT&quot;m))))<br />dispatch))<br />
  21. 21. serialized-exchange<br />(define(serialized-exchangeaccount1 account2)<br />(let((serializer1(account1&apos;serializer))<br />(serializer2(account2&apos;serializer)))<br />((serializer1(serializer2exchange))<br />account1<br />account2)))<br />두 계정의 줄 세우개serializer1, serializer2를 사용해 exchange 프로시저 전체를 줄 세운 프로시저로 만들었다.<br />
  22. 22. 연습문제 3.44<br />돈을 맞바꾸는 문제처럼 transfer 프로시저 자체를 줄 세운 프로시저로 만들어야 하는가?<br />(define(transferfrom-account to-account amount)<br />((from-account&apos;withdraw)amount)<br />((to-account&apos;deposit)amount))<br />
  23. 23. 연습문제 3.44 풀이<br />필요 없다.<br />돈을 맞바꾸는 경우에는 두 은행 계정의 남은 돈의 차이를 계산한 후에 인터럽트가 걸린 경우 두 은행 계정의 남은 돈 차이가 변할 수 있기 때문에 돈을 맞바꾸는 프로시저 전체를 줄 세운 프로시저로 만들었다.<br />돈을 옮기는 프로시저의 경우 인터럽트가 걸려도 프로시저 동작에 이상 없다.<br />
  24. 24. 연습문제 3.45<br />serialized-exchange를 불러 쓸 때 어떤 일이 일어나는지 따져라<br />(define(make-account-and-serializerbalance)<br />(define(withdrawamount)<br />(if(&gt;=balance amount)<br />(begin(set!balance (-balance amount))<br />balance)<br />&quot;Insufficient funds&quot;))<br />(define(depositamount)<br />(set!balance (+balance amount))<br />balance)<br />(let((balance-serializer(make-serializer)))<br />(define(dispatchm)<br />(cond((eq?m &apos;withdraw)(balance-serializerwithdraw))<br />((eq?m &apos;deposit)(balance-serializerdeposit))<br />((eq?m &apos;balance)balance)<br />((eq?m &apos;serializer)balance-serializer)<br />(else(error&quot;Unknown request -- MAKE-ACCOUNT&quot;m))))<br />dispatch))<br />
  25. 25. 연습문제 3.45 풀이<br />serialized-exchange 프로시저는 두 계정의 줄 세우개로 프로시저 전체를 줄 세운 프로시저로 만든다.<br />안에서 exchange 프로시저를 실행하는데, withdraw, deposit 프로시저가 실행되지 않고 하염없이 기다린다.<br />계정의 줄 세우개로 프로시저를 실행했기 때문에.<br />
  26. 26. make-serializer구현<br />뮤텍스(mutex)<br />mutual exclusion : 상호 배제<br />뮤텍스 물체를 쥐거나(acquired) 풀어 주는(release) 연산<br />한 프로세스가 뮤텍스를 잡으면 풀어 놓을 때까지 다른 프로세스가 뮤텍스를 잡지 못한다.<br />줄 세우개 하나에 뮤텍스 하나.<br />
  27. 27. (define(make-serializer)<br />(let((mutex(make-mutex)))<br />(lambda(p)<br />(define(serialized-p.args)<br />(mutex&apos;acquire)<br />(let((val(applyp args)))<br />(mutex&apos;release)<br />val))<br />serialized-p)))<br />(define(make-mutex)<br />(let((cell(listfalse)))<br />(define(the-mutexm)<br />(cond((eq?m &apos;acquire)<br />(if(test-and-set!cell)<br />(the-mutex&apos;acquire))); 재시도<br />((eq?m &apos;release)(clear!cell))))<br />the-mutex))<br />(define(clear!cell)<br />(set-car!cell false))<br />
  28. 28. test-and-set! 구현<br />(define(test-and-set!cell)<br />(if(carcell)<br />true<br />(begin(set-car!cell true)<br />false)))<br />이렇게 구현하면 제대로 동작 안 한다.<br />병행성 제어를 집어넣어야 할 곳<br />한 알갱이로(atomically) 처리되어야 한다.<br />하드웨어 수준에서 지원하는 프로시저를 사용.<br />MIT Scheme : without-interrupts<br />
  29. 29. 연습문제 3.47<br />세마포어(semaphore)를 뮤텍스와test-and-set!을 써서 만들어라.<br /><ul><li> 잡았다 놓았다 하는 연산은 뮤텍스와 같지만 n개 프로세스가 병행으로 세마포어를 쥘 수 있다.
  30. 30. 뮤텍스를 사용하는 것만 풀이</li></li></ul><li>연습문제 3.47 풀이<br />(define(new-make-semaphoren)<br />(let((count0)<br />(mutex(make-mutex)))<br />(define(the-semaphorem)<br />(cond((eq?m &apos;acquire)<br />(mutex&apos;acquire)<br />(cond((&gt;count n)<br />(mutex&apos;release)<br />(the-semaphore&apos;acquire)); 재시도<br />(else<br />(set!count (+count 1))<br />(mutex&apos;release))))<br />((eq?m &apos;release)<br />(mutex&apos;acquire)<br />(if(&lt;count 0)<br />(set!count (-count 1)))<br />(mutex&apos;release))))<br />the-semaphore))<br />
  31. 31. 데드락(deadlock)<br />여러 프로세스가 다른 프로세스를 지켜보면서 아무것도 하지 못하고 끝없이 기다려야 하는 상태<br />돈 맞바꾸는 문제의 경우에는 계정마다 번호를 매겨 놓고 모든 프로세스가 언제나 번호가 낮은 계정을 움켜쥐고 일을 시작하도록 하면 해결 가능.<br />
  32. 32. 연습문제 3.48<br />계정에 번호를 매겨, 각 프로세스가 처음에 더 작은 번호를 매긴 계정을 움켜쥐도록 만들어서 데드락을 피하는 기법을 사용.<br />왜 돈 맞바꾸는 문제에서 데드락에 빠지지 않는가?<br />그 방법대로 serialized-exchange 프로시저를 작성.<br />
  33. 33. 연습문제 3.48 풀이<br />(define(make-account-and-serializerid balance)<br />(define(withdrawamount)<br />(if(&gt;=balance amount)<br />(begin(set!balance (-balance amount))<br />balance)<br />&quot;Insufficient funds&quot;))<br />(define(depositamount)<br />(set!balance (+balance amount))<br />balance)<br />(let((balance-serializer(make-serializer)))<br />(define(dispatchm)<br />(cond((eq?m &apos;withdraw)withdraw)<br />((eq?m &apos;deposit)deposit)<br />((eq?m &apos;balance)balance)<br />((eq?m &apos;id)id)<br />((eq?m &apos;serializer)balance-serializer)<br />(else(error&quot;Unknown request -- MAKE-ACCOUNT&quot;m))))<br />dispatch))<br />
  34. 34. 연습문제 3.48 풀이(계속)<br />(define(serialized-exchangeaccount1 account2)<br />(let((serializer1(account1&apos;serializer))<br />(serializer2(account2&apos;serializer)))<br />(if(&lt;(account1&apos;id)(account2&apos;id))<br />((serializer2(serializer1exchange))account1 account2)<br />((serializer1(serializer2exchange))account1 account2))))<br />비교 대상이 되는 id가 있어서 어떠한 계정 두개를 가져다 놓더라도 줄 세우는 방법은 한가지 밖에 없다. 그래서 데드락에 빠지지 않는다.<br />
  35. 35. 끝<br />

×