<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>LOV3</title>
    <link>https://gothax.tistory.com/</link>
    <description>기술블로그</description>
    <language>ko</language>
    <pubDate>Mon, 25 May 2026 22:09:55 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>grammiboii</managingEditor>
    <item>
      <title>[OS 공룡책] 6. Synchronization Tools, 7. Examples</title>
      <link>https://gothax.tistory.com/80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동시 접근이 일어나면 항상 발생하는 문제가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;data inconsistency - 일관성 문제이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JVM에서 공부했던 내용이라 간략하게만 언급하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스레드는 메모리를 공유하기 때문에 - 정확하게는 힙 영역을 공유하기 때문에 발생한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;423&quot; data-origin-height=&quot;410&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cePduE/dJMcabJGJvA/SVP8ddnaPopvnEH9w1PUqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cePduE/dJMcabJGJvA/SVP8ddnaPopvnEH9w1PUqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cePduE/dJMcabJGJvA/SVP8ddnaPopvnEH9w1PUqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcePduE%2FdJMcabJGJvA%2FSVP8ddnaPopvnEH9w1PUqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;423&quot; height=&quot;410&quot; data-origin-width=&quot;423&quot; data-origin-height=&quot;410&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;c언어 예시이긴 하지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sum++이 결국 sum (현재 값을 읽고-&amp;gt;증가된 값 쓰기) 로직이니까&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동시에 접근하는 값이 최신 값이 아니게 되면서 정합성이 깨지기 시작한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 고급1에서 너무 많이했으니 패스&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;Race Condition&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어로 교착상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러개의 프로세스가 하나의 값 수정을 할때 발생하는 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교착상태가 발생하는 코드 구역을 ciritical section이라고 부르는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세부적으로 코드 영역을 4가지로 구분한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 아직 락을 배우지 않았지만 언급하겠다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- entry section&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; require permission - 락을 획득해야 진입할 수 있는 구간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- critical section&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 임계영역으로 race condition이 발생하는 구간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- exit section&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ciritical section이 끝나는 구간으로 락을 반납해야할 것이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- remainder section&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 나머지~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 critical section 문제를 해결하기 위한 3가지 요구사항이 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- mutual exclusion&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 상호 배제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 하나의 프로세스가 critical section을 실행하고 있다면 다른 프로세스는 실행할 수 없어야 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- progress (avoid deadlock)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 프로세스가 critical section을 실행하고 있지 않음에도&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 다른 프로세스가 진입하지 못하는 경우가 없어야 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- bounded waiting (avoid starvation)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 락을 획득하기 위해 기다리는 프로세스들이 있을텐데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 락 획득에 우선순위를 둔다면 cpu scheduling때와 마찬가지로 우선순위에 계속 밀려 락을 획득하지 못하는 경우가 없어야 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 mutual exclusion은 너무 필수적인거고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 두가지를 모두 발생하지 않도록 하는 것은 매우 어렵다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이게 발생했을 때 어떻게 할것인지가 중요한 포인트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cczZr2/dJMcagEeA6F/nIk0gJY5AYLKQTDFfWrkN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cczZr2/dJMcagEeA6F/nIk0gJY5AYLKQTDFfWrkN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cczZr2/dJMcagEeA6F/nIk0gJY5AYLKQTDFfWrkN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcczZr2%2FdJMcagEeA6F%2FnIk0gJY5AYLKQTDFfWrkN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;680&quot; height=&quot;412&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;412&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;single core에서는 문제를 해결하는 것이 간단하다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;259&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/emMqCs/dJMcai9OxnY/gqD9KSksVac0SKppCXhHuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/emMqCs/dJMcai9OxnY/gqD9KSksVac0SKppCXhHuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/emMqCs/dJMcai9OxnY/gqD9KSksVac0SKppCXhHuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FemMqCs%2FdJMcai9OxnY%2FgqD9KSksVac0SKppCXhHuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;503&quot; height=&quot;259&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;259&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;읽기 -&amp;gt; 더하기 -&amp;gt; 더한값 쓰기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수행될 동안 interrupt되지 않도록 하면 된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 atomic하게 수행하면 된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면에 코어가 여러개라면 다른 코어에서 실행하는 경우도 문제가 되고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처리가 오래 걸린다면 코어가 놀게되는 즉 cpu utilization 문제가 발생한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;Peterson's Solution&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;693&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MLxuR/dJMcaaYiR5S/eTeJmZ4iltIkwLKdi4f3W0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MLxuR/dJMcaaYiR5S/eTeJmZ4iltIkwLKdi4f3W0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MLxuR/dJMcaaYiR5S/eTeJmZ4iltIkwLKdi4f3W0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMLxuR%2FdJMcaaYiR5S%2FeTeJmZ4iltIkwLKdi4f3W0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;693&quot; height=&quot;294&quot; data-origin-width=&quot;693&quot; data-origin-height=&quot;294&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;soft ware based로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원시적인 락을 건거다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이 방법은&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;while 문을 도는 busy waiting 즉 spin lock이라는 문제점이 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;Hardware based solutions&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 하드웨어를 다뤄야 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- memory barriers or fences&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- hardware instructions&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- atomic variables&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;611&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLAyPS/dJMcabJGKkq/BrXON2oBxKxuH6j53UEdpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLAyPS/dJMcabJGKkq/BrXON2oBxKxuH6j53UEdpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLAyPS/dJMcabJGKkq/BrXON2oBxKxuH6j53UEdpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLAyPS%2FdJMcabJGKkq%2FBrXON2oBxKxuH6j53UEdpk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;611&quot; height=&quot;341&quot; data-origin-width=&quot;611&quot; data-origin-height=&quot;341&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 내용은 보너스 느낌으로 나온 것 같다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;살짝 복기해보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 고급편에서는 이런 자료형이나 CAS 연산은 살짝만 알아보고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 활용하는 concurrent 컬렉션을 알아봤었다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본격적으로 OS 레벨의 락은 이제 나온다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;Mutex Locks&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mutual exclusion을 줄여서 mutex&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;락을 획득하고, 반납하는 구조&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;375&quot; data-origin-height=&quot;266&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwNLxP/dJMcahiONR0/kKwZK7KAOSyrdY8Kq1vmw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwNLxP/dJMcahiONR0/kKwZK7KAOSyrdY8Kq1vmw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwNLxP/dJMcahiONR0/kKwZK7KAOSyrdY8Kq1vmw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwNLxP%2FdJMcahiONR0%2FkKwZK7KAOSyrdY8Kq1vmw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;375&quot; height=&quot;266&quot; data-origin-width=&quot;375&quot; data-origin-height=&quot;266&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아까 나온 peterson이랑 사실은 비슷하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 문제점이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- spinlock (context switch 비용을 아낄수는 있다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- n개를 처리할 수 없다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- interrupt를 차단할 수 없다면 문제가 발생한다(멀티코어)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;Semaphore&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세마포어는 신호기라는 말이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 구현에서는 그냥 integer 변수다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;597&quot; data-origin-height=&quot;202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bj15kr/dJMcacPlBW1/d3rENwzoEDkHqkyLGugiNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bj15kr/dJMcacPlBW1/d3rENwzoEDkHqkyLGugiNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bj15kr/dJMcacPlBW1/d3rENwzoEDkHqkyLGugiNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbj15kr%2FdJMcacPlBW1%2Fd3rENwzoEDkHqkyLGugiNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;597&quot; height=&quot;202&quot; data-origin-width=&quot;597&quot; data-origin-height=&quot;202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전에 나온 mutex와 차이점은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mutex에서는 락하나를 두고 받고, 반납하는 방식인데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 전역변수를 증가, 감소하는 방식을 사용하는 것이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현차이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- binary semaphore를 사용한다면 즉 0, 1만 사용하면 mutex와 같은 것이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- counting semaphore&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; n개를 사용 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;906&quot; data-origin-height=&quot;444&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CWjDv/dJMcaacVBS7/ZL3D6pvHrrqxNuj4FkyzH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CWjDv/dJMcaacVBS7/ZL3D6pvHrrqxNuj4FkyzH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CWjDv/dJMcaacVBS7/ZL3D6pvHrrqxNuj4FkyzH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCWjDv%2FdJMcaacVBS7%2FZL3D6pvHrrqxNuj4FkyzH1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;906&quot; height=&quot;444&quot; data-origin-width=&quot;906&quot; data-origin-height=&quot;444&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;구체적으로&lt;/s&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;wait(), signal()을 사용하게 되는데&lt;/s&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;여기부터 락 획득을 대기하는 wait set 개념이 나오게 되는 것이다&lt;/s&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;이로 인해 waiting queue에 들어가게 되면 busy waiting 문제도 해결된다&lt;/s&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;이건 semaphore 구현 방식 중에서도 차이가 있는거라 지금 논점은 mutex -&amp;gt; semaphore -&amp;gt; monitor 발전이니까 생각하지 말자&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뮤텍스 / 세마포어를 사용한다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;timing error가 발생할 수 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 예시로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;wait -&amp;gt; signal 순서만 헷갈려도 심각한 에러가 날 가능성이 존재한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;Monitor&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해 간단하게 사용 가능한 고 수준으로 동기화를 다룰 수 있는 모니터를 제공한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;422&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Arhq9/dJMcac2QwTN/SMxjjsv6ghwGlNKhZDqXiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Arhq9/dJMcac2QwTN/SMxjjsv6ghwGlNKhZDqXiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Arhq9/dJMcac2QwTN/SMxjjsv6ghwGlNKhZDqXiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FArhq9%2FdJMcac2QwTN%2FSMxjjsv6ghwGlNKhZDqXiK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;492&quot; height=&quot;422&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;422&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 생산자, 소비자 문제에서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 그룹을 깨울지에 대한 문제가 생기는걸 확인했었다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해 conditional variable이 필요하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;601&quot; data-origin-height=&quot;378&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A3CiY/dJMcafk0nXw/A1FXwsPr3P1hkLLGKYsp91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A3CiY/dJMcafk0nXw/A1FXwsPr3P1hkLLGKYsp91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A3CiY/dJMcafk0nXw/A1FXwsPr3P1hkLLGKYsp91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA3CiY%2FdJMcafk0nXw%2FA1FXwsPr3P1hkLLGKYsp91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;601&quot; height=&quot;378&quot; data-origin-width=&quot;601&quot; data-origin-height=&quot;378&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;자바에서 제공하는 모니터락&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;객체마다 가지고 있었던 모니터락 기억나쥬?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;675&quot; data-origin-height=&quot;409&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0zvDs/dJMcagjUdp2/G5TcmpMSTpKcf8ZlDxgnok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0zvDs/dJMcagjUdp2/G5TcmpMSTpKcf8ZlDxgnok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0zvDs/dJMcagjUdp2/G5TcmpMSTpKcf8ZlDxgnok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0zvDs%2FdJMcagjUdp2%2FG5TcmpMSTpKcf8ZlDxgnok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;675&quot; height=&quot;409&quot; data-origin-width=&quot;675&quot; data-origin-height=&quot;409&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적으로 두가지가 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- synchronized&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 객체 단위로 임계영역/메서드를 묶어주는 키워드였다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- wait(), notify()&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Object 클래스에 선언되어서 모든 객체가 가지고 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;wait() 메서드로 모니터락 획득하러 대기 (ready queue)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;notify()는 락을 반납하면서 해당 wait set에 있는 스레드 깨움&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 헷갈려서 비교해달라고 했더니 이렇다고 한다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;510&quot; data-origin-height=&quot;170&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ueEZ1/dJMcag5iq27/5XeK9wHSntjY1N7xCemK7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ueEZ1/dJMcag5iq27/5XeK9wHSntjY1N7xCemK7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ueEZ1/dJMcag5iq27/5XeK9wHSntjY1N7xCemK7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FueEZ1%2FdJMcag5iq27%2F5XeK9wHSntjY1N7xCemK7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;510&quot; height=&quot;170&quot; data-origin-width=&quot;510&quot; data-origin-height=&quot;170&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Liveness&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뮤텍스 / 세마포어 / 모니터 모두 mutual exclusion 문제를 해결하지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deadlock, starvation 문제를 고려하지 않는다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 고려한 것이&amp;nbsp; liveness&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자세하게 알 필요는 없다고 하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데드락/starvation은 뒤에서 자세히 나온다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;동시성 제어 문제 실질적인 문제들을 다룬다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- bounded-buffer problem&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 전에 살펴봤던 생산자 소비자 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- readers-writers problem&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;여러개의 프로세스들이 shared data에 접근하는 것은 동일하지만 어떤 프로세스는 read만, 어떤 프로세스는 read+write 한다는 가정이 다르다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; data inconsistency를 일으키는건 writer이기 때문에 writer에게 우선적으로 락을 점유할 기회를 줄것인지, reader writer 모두 공평하게 락을 획득할 기회를 줄것인지에 대한 고민이 존재한다 -&amp;gt; 현재는 Redaer Writer Locks라는 표준화된 해결 기법이 존재하기 때문에 개발자는 고민하지 않아도 된다고 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- dining-philosophers problem&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 대표적인 동기화 문제인데 철학자 5명 사이에 젓가락이 하나씩 5개가 있다는 가정하에 생기는 문제다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 단순히 생각하면 젓가락을 동시에 집지 못하도록 락을 걸어 mutual exclusive하게 하면 되는거 아닌가? 이지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 동시에 모든 철학자가 자신 기준 왼쪽 젓가락을 잡는다면? - deadlock&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 1, 2, 3, 4, 5순으로 원형으로 앉아있다고 하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 1, 3이 밥을 번갈아 가면서 먹으면 철학자 2는 영원히 밥을 먹지 못할 것이다 - starvation&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;404&quot; data-origin-height=&quot;313&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQ2ami/dJMcaiILPVe/OwRocBcMv5GQaonda9P4UK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQ2ami/dJMcaiILPVe/OwRocBcMv5GQaonda9P4UK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQ2ami/dJMcaiILPVe/OwRocBcMv5GQaonda9P4UK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQ2ami%2FdJMcaiILPVe%2FOwRocBcMv5GQaonda9P4UK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;404&quot; height=&quot;313&quot; data-origin-width=&quot;404&quot; data-origin-height=&quot;313&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결책으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왼쪽 오른쪽 젓가락을 모두 집을 수 있을때만 집는 방법을 떠올릴 수 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 구체적으로 모니터를 사용해 이를 해결하는 법을 알아보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;젓가락을 드는 메커니즘이 원래는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;thinking (젓가락 사용X) -&amp;gt; eating (젓가락 사용)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인데 hungry 상태를 추가해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;thinking -&amp;gt; hungry -&amp;gt; eating 상태로 관리한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hungry 상태는 락을 점유하기 위해 기다리는, wait set을 떠올리면 된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 mutex, deadlock은 방지할 수 있지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;starvation을 방지할 수는 없다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CAP이론처럼 여기서도 3가지(mutex, deadlock, starvation)를 모두 달성하기는 매우 어렵기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/OS</category>
      <author>grammiboii</author>
      <guid isPermaLink="true">https://gothax.tistory.com/80</guid>
      <comments>https://gothax.tistory.com/80#entry80comment</comments>
      <pubDate>Fri, 9 Jan 2026 19:10:08 +0900</pubDate>
    </item>
    <item>
      <title>[OS 공룡책] 5. CPU Scheduling</title>
      <link>https://gothax.tistory.com/79</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 cpu를 왜 sharing 해야하는지는 처음에 알아봤다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복습해보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전제는 cpu는 굉장히 빠르기 때문에 처리량에 비해 놀고 있는 상황이고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cpu utilization 즉 사용량을 극대화 하기 위해 여러가지 프로세스를 번갈아 가며 처리하기 위함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 기본적으로 IO bound가 cpu bound보다 훨씬 길기 때문에 발생한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 cpu를 어떤 프로세스에게 어떻게 분배할것인가? 가 스케줄링이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀더 구체적으로 ready queue에 들어가있는 프로세스들에게 어떻게 할당할것인가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크게 두가지가 있는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- FIFO Queue&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Priority Queue&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 구체적인 방법론을 이해하기 위해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Preemptive 선점형&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Non-preemptive 비선점형&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개념이 나온다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 말이 좀 헷갈리는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주체는 cpu 스케줄러이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cpu 스케줄러가 &lt;b&gt;preemptive하면 즉 선점형이면&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;현재 돌아가고 있는 프로세스들을 쫓아낼 수 있는 것&lt;/b&gt;이고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;non preemptive하면 한번 점유한 프로세스는 자발적으로 끝나거나 waiting 상태가 될때까지 돌아간다는 것&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 하나더 몰랐던건&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;context switching때 switch할 다음 작업을 선택하는 것이 스케줄러이고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택된 작업을 프로세서에게 할당하는 것은 dispatcher라고 따로 있다고 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 본론으로 돌아와 스케줄링할때 가장 중요한 지표는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- waiting time&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- turnaround time&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;들어가기 앞서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 당연해보이지만 헷갈리는 부분은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스를 기준으로 스케줄링한다고 배우는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실질적으로는 스레드 단위로 스케줄링 하는게 일반적이라고 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스케줄링 알고리즘&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 목록부터 보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- FCFS : first come first served (Non - preemptive)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- SJF / &lt;b&gt;SRTF&lt;/b&gt; : Shortest Job First / &lt;b&gt;Shortest Remaining Time First&lt;/b&gt; (Non - preemptive / &lt;b&gt;preemptive&lt;/b&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;time sharing&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- RR : Round Robin&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Priority Based&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- MLQ : Multi Level Queue&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- MLFQ : Multi Level Feedback Queue&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;FCFS&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 간단하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fifo 큐에 넣어주면 된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Non - preemptive&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;431&quot; data-origin-height=&quot;207&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rrwLq/dJMcai9OvZw/vGqGC6bd503KrzgfC5VVQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rrwLq/dJMcai9OvZw/vGqGC6bd503KrzgfC5VVQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rrwLq/dJMcai9OvZw/vGqGC6bd503KrzgfC5VVQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrrwLq%2FdJMcai9OvZw%2FvGqGC6bd503KrzgfC5VVQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;325&quot; height=&quot;156&quot; data-origin-width=&quot;431&quot; data-origin-height=&quot;207&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BEmJb/dJMcai9OvZy/OybK1ITbA1Fy9cyScWlKE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BEmJb/dJMcai9OvZy/OybK1ITbA1Fy9cyScWlKE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BEmJb/dJMcai9OvZy/OybK1ITbA1Fy9cyScWlKE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBEmJb%2FdJMcai9OvZy%2FOybK1ITbA1Fy9cyScWlKE0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;733&quot; height=&quot;146&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;166&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;waiting time&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P1 : 0&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P2 : 24&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P3 : 27&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평균 17초를 기다린다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;turn around time&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P1 : 24&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P2 : 27&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P3 : 30&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완료될때까지 평균 27초&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9cHo6/dJMcadUYfhy/IT9j3nOjrfkMOAnli2gPUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9cHo6/dJMcadUYfhy/IT9j3nOjrfkMOAnli2gPUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9cHo6/dJMcadUYfhy/IT9j3nOjrfkMOAnli2gPUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9cHo6%2FdJMcadUYfhy%2FIT9j3nOjrfkMOAnli2gPUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;792&quot; height=&quot;186&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;waiting time&lt;br /&gt;P1 : 6&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P2 : 0&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P3 : 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평균 3초를 기다렸다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P1 : 30&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P2 : 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P3 : 6&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완료될때까지 평균 13초&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;들어오는 순서만 바뀌었는데 엄청난 차이가 난다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근본적으로 실행시간이 짧은데도 오래 기다려야 하기 때문에 이런 일이 발생한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;SJF Shortest Job First &amp;amp; SRTF Shortest Remaining Time First&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 문제를 해결하기 위해 실행시간이 가장 짧은 프로세스를 실행하는 아이디어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Non - preemptive OR preemptive&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;409&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kLrxt/dJMcafL4o01/nevZHS6rZzzdhdkXwCpaEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kLrxt/dJMcafL4o01/nevZHS6rZzzdhdkXwCpaEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kLrxt/dJMcafL4o01/nevZHS6rZzzdhdkXwCpaEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkLrxt%2FdJMcafL4o01%2FnevZHS6rZzzdhdkXwCpaEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;674&quot; height=&quot;338&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;409&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도착 순서와 무관하게 하나의 간트차트가 나온다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;waiting time&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P1 : 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P2 : 16&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P3 : 9&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P4 : 0&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평균 7초&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 preemptive일수도 있는가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P1이 5초 작업이 걸리고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P2가 1초 작업이 걸리는데 P1을 1초 실행중에 P2가 들어온다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P1 -&amp;gt; P2 -&amp;gt; P1순으로 작업할 수도 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 SRTF이다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;335&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnzhha/dJMcagqFvZN/0aMCIP9p5N51ebpiu8dRfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnzhha/dJMcagqFvZN/0aMCIP9p5N51ebpiu8dRfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnzhha/dJMcagqFvZN/0aMCIP9p5N51ebpiu8dRfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbnzhha%2FdJMcagqFvZN%2F0aMCIP9p5N51ebpiu8dRfk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;706&quot; height=&quot;296&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;335&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;RR Round Robin&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CS에서 되게 많이 나오는 말인데 빙글빙글 돈다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 고루고루 돌아가면서 쓰는 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;preemptive - time sharing&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 time quantum&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단위시간동안 쓰고 돌아가는 방식이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 10 ~ 100 ms사이를 사용한다고 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현은 circular queue사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;359&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0SkMA/dJMcachvuW2/NWQlFul3nXHrZnrqoruK60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0SkMA/dJMcachvuW2/NWQlFul3nXHrZnrqoruK60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0SkMA/dJMcachvuW2/NWQlFul3nXHrZnrqoruK60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0SkMA%2FdJMcachvuW2%2FNWQlFul3nXHrZnrqoruK60%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;703&quot; height=&quot;326&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;359&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;time quantum을 얼마로 두느냐가 굉장히 중요한 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;555&quot; data-origin-height=&quot;442&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bW4yWG/dJMcabXc5VF/CViMLv8ZJuQQmEMygSoJA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bW4yWG/dJMcabXc5VF/CViMLv8ZJuQQmEMygSoJA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bW4yWG/dJMcabXc5VF/CViMLv8ZJuQQmEMygSoJA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbW4yWG%2FdJMcabXc5VF%2FCViMLv8ZJuQQmEMygSoJA1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;466&quot; height=&quot;371&quot; data-origin-width=&quot;555&quot; data-origin-height=&quot;442&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너무 적게 줘도 turn around time이 늘어나고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넘누 많이 줘도 문제다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Priority Based&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스에 우선순위를 부여해 실행하는 방식이고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 프로세스 우선순위가 같다면 FCFS 순으로 먼저 들어온 프로세스를 먼저 처리한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SJF가 일종의 priorioty based라고 볼 수 있다 &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; SJF에서 next cpu burst를 예상해 계산하기 때문 (수행 시간을 우선순위로 두는 것)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;775&quot; data-origin-height=&quot;411&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/drEKc7/dJMcaacVyMu/tyq9dBRnuyOGI0IpEm1DWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/drEKc7/dJMcaacVyMu/tyq9dBRnuyOGI0IpEm1DWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/drEKc7/dJMcaacVyMu/tyq9dBRnuyOGI0IpEm1DWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdrEKc7%2FdJMcaacVyMu%2Ftyq9dBRnuyOGI0IpEm1DWk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;775&quot; height=&quot;411&quot; data-origin-width=&quot;775&quot; data-origin-height=&quot;411&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 알고리즘에서는 starvation 문제가 발생할 수 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(우선순위가 높은것만 계속 실행하는 문제)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해 aging을 사용할 수 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행하지 못한 프로세스의 우선순위를 높여주는 방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 여기서 preemptive하게 할것인가 non-preemptive하게 할것인가 선택이 존재한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론적으로 RR + Priority 섞어서 사용하게 되는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 우선순위를 가지면 RR&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/OS</category>
      <author>grammiboii</author>
      <guid isPermaLink="true">https://gothax.tistory.com/79</guid>
      <comments>https://gothax.tistory.com/79#entry79comment</comments>
      <pubDate>Fri, 9 Jan 2026 18:10:53 +0900</pubDate>
    </item>
    <item>
      <title>[OS 공룡책] 4. Thread &amp;amp; Concurrency</title>
      <link>https://gothax.tistory.com/78</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 프로그램에서도 여러가지 동작을 동시에 수행할 수 있다는 점에서 스레드가 필요하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;spring을 배우면서 그렇게 했던 스레드풀, 스택영역 등..이 이제 여기와 관련된 내용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀티스레딩을 하면 좋은점은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Responsiveness&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 연속적인 응답을 가능하게 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Resource Sharing&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 스레드는 프로세스와 달리 메모리 공간을 공유하기 때문에 shared-memory나 message passing 방식보다 훨씬 쉽다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 좀더 정확히는 JVM 구조 공부했을 때처럼 힙영역, 메서드 영역을 공유한다고 보면 될 것 같다. (Thread Local같은 예외도 있다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Economy&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 프로세스 생성보다 훨씬 저렴하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; context swithching보다 thread switching이 overhead가 훨씬 적다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- scalability&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 프로세서에서는 이 멀티스레딩 구조가 쉬울텐데, 현대에는 멀티코어 시스템을 사용하기 때문에 훨씬 더 복잡해진다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 여러개의 스레드가 물리적으로 동일한 시간에 돌아가는 parallel한 개념이 나오기 때문에 동시성 문제가 더 생기는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 이게 자바 고급편에서 주로 다뤘던 내용이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 문제가 생기냐면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- identifying tasks&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 일을 쪼개서 각 스레드에게 어떤 일을 시킬것인지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- balance&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 각 스레드에게 얼마나 일을 쪼개서 시킬것인지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- data splitting&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- data dependency&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- test and debugging&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ 분산시스템이 나오면서 이게 더 복잡해졌다고 첨언도 나온다,, 저번 학기에 지겹게 배웠던 분산시스템..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;스레드 종류&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- user thread&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; java에서 일반적으로 사용하는 스레드를 예시로 들 수 있겠다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- kernel thread&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 시스템에 접근하기 위해 사용하는 native thread&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 내용은 다 배운 기억이 잘 나는데 이건 기억이 전혀 안난다..? 기억을 못하는건가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 좀 자세하게 알아보자&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;384&quot; data-origin-height=&quot;231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CWVTg/dJMcafk0hFa/ibeVMe7FPUGXITk4cuJBP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CWVTg/dJMcafk0hFa/ibeVMe7FPUGXITk4cuJBP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CWVTg/dJMcafk0hFa/ibeVMe7FPUGXITk4cuJBP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCWVTg%2FdJMcafk0hFa%2FibeVMe7FPUGXITk4cuJBP1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;384&quot; height=&quot;231&quot; data-origin-width=&quot;384&quot; data-origin-height=&quot;231&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;user thread와 kernel thread의 관계에서는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- many to one model&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 커널 스레드 하나가 여러개의 유저 스레드를 매핑&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;239&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ce6ax8/dJMcaiBYMSI/YJbJke4eopdB7DOusIKCeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ce6ax8/dJMcaiBYMSI/YJbJke4eopdB7DOusIKCeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ce6ax8/dJMcaiBYMSI/YJbJke4eopdB7DOusIKCeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fce6ax8%2FdJMcaiBYMSI%2FYJbJke4eopdB7DOusIKCeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;280&quot; height=&quot;161&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;239&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- one to one model&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 하나의 커널 스레드가 하나의 유저 스레드를&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- many to many model&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러면서 어플리케이션에서 커널 스레드를 쉽게 다루기 위한 pthread 개념이 나온다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유닉스 계열에서는 Posix thread이고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;윈도우는 자체 윈도우 스레드가 있다고 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;many to one 방식은 비효율적이고 멀티코어를 사용하기 힘들기 때문에 잘 사용하지 않고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바에서 사용하는 방식이 one to one이고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GO언어에서 사용하는 방식이 many to many라고 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 자바에서 스레드를 하나 늘릴때마다 OS 스레드도 하나 늘어나게 되는거고..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;--&amp;gt; 너무 당연히 one to one이라고 생각했던 나를 반성하게 되는게&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;413&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRkSW0/dJMb99SC812/v419z5CwUZRrKzfefoAt2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRkSW0/dJMb99SC812/v419z5CwUZRrKzfefoAt2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRkSW0/dJMb99SC812/v419z5CwUZRrKzfefoAt2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRkSW0%2FdJMb99SC812%2Fv419z5CwUZRrKzfefoAt2K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;413&quot; height=&quot;296&quot; data-origin-width=&quot;413&quot; data-origin-height=&quot;296&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모니터링할때 os에 떠있는 스레드 개수가 스레드풀 개수랑 비슷하겠지라고 생각했다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 지금은 맞는 말이지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 many to many 방식을 사용한다면 OS 스레드 개수는 서버의 스레드풀 개수에 비해 훨씬 적었을 것 같다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;--&amp;gt; 이와 관련해 JAVA21에서 virtual thread 기능이 추가되었다고 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;go routine처럼 many to many 매핑이 가능하다고 하는데,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여태까지 왜 17썼지..? 정확하지는 않으니 나중에 따로 정리해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/OS</category>
      <author>grammiboii</author>
      <guid isPermaLink="true">https://gothax.tistory.com/78</guid>
      <comments>https://gothax.tistory.com/78#entry78comment</comments>
      <pubDate>Thu, 8 Jan 2026 23:32:36 +0900</pubDate>
    </item>
    <item>
      <title>[OS 공룡책] 3. Process</title>
      <link>https://gothax.tistory.com/77</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OS를 다 까먹어서 복습해보기로.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1, 2챕터는 인트로여서 정리하지는 않겠다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로세스&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너무 많이 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스 : 실행중인 프로그램&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 OS가 프로세스를 관리해주야 하는데 어떻게 관리할것인가? 가 관건이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 이해하기 위해 프로세스의 생명주기를 이해해야 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;프로세스 생명주기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- NEW&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 프로세스가 생성된 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- RUNNING&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 프로세스가 CPU를 점유해서 해당 명령어를 CPU가 처리하고 있는 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- WAITING&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; CPU가 다른 처리를 하고 있어서 기다리고 있는 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; EX) 프로세스1이 running 상태일때 프로세스2가 기다리고 있는 상황&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; EX2) IO를 일으켜서 점유를 반납하는 상황&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- READY&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 레디큐에서 CPU 점유를 대기하고 있는 상황&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; EX) IO를 일으키고 waiting도 끝난 다음 대기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- TERMINATED&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 모두 처리된 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVJk63/dJMcagYtTc7/nNilqk9p9Gr06epWUE5et0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVJk63/dJMcagYtTc7/nNilqk9p9Gr06epWUE5et0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVJk63/dJMcagYtTc7/nNilqk9p9Gr06epWUE5et0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVJk63%2FdJMcagYtTc7%2FnNilqk9p9Gr06epWUE5et0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;649&quot; height=&quot;320&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;320&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PCB (process control block)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCB라고 부르기도 한다고 한다&amp;nbsp; (task control block)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생명주기 알았고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이 생명주기들을 가지는 프로세스를 정말 어떻게 관리할 것인가?가 PCB이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 프로세스가 가져야할 정보를 모두 하나의 구조체에 저장하자는 아이디어가 PCB&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 PCB는 &lt;b&gt;메모리에 존재&lt;/b&gt;하는 자료구조이고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 정보들을 저장한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- process state : 상태 (new, running 등)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- program counter :&amp;nbsp; 다음으로 실행할 명령어의 메모리 주소 저장하는 레지스터 (CPU에 있겠지?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 컨텍스트 스위칭이 일어나고 다시 실행할때 다음 실행할 주소를 기억해야 하니까&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- CPU 레지스터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- CPU 스케줄링 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 메모리 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 열린 파일 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;등&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;--&amp;gt; 내용들을 생각해보면 PCB는 프로세스마다 하나씩 있겠구나를 생각해볼 수 있다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;339&quot; data-origin-height=&quot;413&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mVjx2/dJMcagxpVxK/3Qx3UcVaZ0pfDFeSE8zc00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mVjx2/dJMcagxpVxK/3Qx3UcVaZ0pfDFeSE8zc00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mVjx2/dJMcagxpVxK/3Qx3UcVaZ0pfDFeSE8zc00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmVjx2%2FdJMcagxpVxK%2F3Qx3UcVaZ0pfDFeSE8zc00%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;271&quot; height=&quot;330&quot; data-origin-width=&quot;339&quot; data-origin-height=&quot;413&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스레드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 복습이긴 하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스 내부에서도 여러가지 작업을 처리학 위해 존재하는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행하는 작업의 단위.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스레드는 나중에 다시 나온다고 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;멀티 프로그래밍&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 처음으로 돌아와서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀티 프로그래밍의 목적은&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동시에 여러개의 프로세스를 실행시키기 위함이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 조합해보면 JVM 공부할때 했던 병렬 처리는 하나의 java 프로세스 안에서 스레드 여러개를 처리하는거고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 하고 있는 OS를 공부할때는 컴퓨터 전체 자원 관점에서 여러개의 프로세스를 동시에 실행시키는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 스포티파이를 키고, 브라우저를 실행하면서 워드 프로그램을 띄우는 느낌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 1. at the same time, simultaneously, concurrently는 동일한 의미&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. parallel (병렬적)은 약간 다른 의미&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번 concurrently는 동시성으로 정확히 번갈아가면서 실행하는거다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 그게 엄청 빠르니까 동시처럼 보이는 것 - time sharing과 관련된 내용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2번 parallel은 병렬성으로 진짜 물리적으로 동시에 실행하는거다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 달성하기 위해 사용하는 기법이 스케줄링이고 많이 나왔던게 time sharing, 그중에서도 라운드 로빈 등등..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스케줄링을 위해 프로세스들을 관리하는 것이 ready queue&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1110&quot; data-origin-height=&quot;250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/moIbo/dJMcaaRwf2C/RMwcMWrrimeJaQ4Xi937UK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/moIbo/dJMcaaRwf2C/RMwcMWrrimeJaQ4Xi937UK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/moIbo/dJMcaaRwf2C/RMwcMWrrimeJaQ4Xi937UK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmoIbo%2FdJMcaaRwf2C%2FRMwcMWrrimeJaQ4Xi937UK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1110&quot; height=&quot;250&quot; data-origin-width=&quot;1110&quot; data-origin-height=&quot;250&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IO를 발생시키고는 waiting 상태로 들어간다고 했다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때는 wait queue로 들어가게 될텐데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연히 이 경우에는 큐 개수가 여러개일 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(각 디바이스마다, 즉 인터럽트를 기다리는 대상이 다르기 때문)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;988&quot; data-origin-height=&quot;574&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dylqgA/dJMb99LPxAt/3tJI5G7RAYSpdCQcYyoNFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dylqgA/dJMb99LPxAt/3tJI5G7RAYSpdCQcYyoNFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dylqgA/dJMb99LPxAt/3tJI5G7RAYSpdCQcYyoNFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdylqgA%2FdJMb99LPxAt%2F3tJI5G7RAYSpdCQcYyoNFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;631&quot; height=&quot;367&quot; data-origin-width=&quot;988&quot; data-origin-height=&quot;574&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 작성하는데, 헷갈리면 안되는게 waiting queue에서 인터럽트 받고 바로 running이 아니라 ready queue로 간다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;context switch&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;context?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스의 문맥&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OS 입장에서는 PCB 정보가 프로세스의 context가 되겠다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;interrupt 상황을 보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 running중인 프로세스의 context를 저장하고 (EX) PC)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커널 모드로 들어가 다른 작업을 수행하거나 ready queue에 있는 다음 프로세스를 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로세스 생성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fork()라는 system call 명령어를 사용한다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;현재 프로세스를 복제해서 자식 프로세스를 만드는 작업이다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;678&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9DikE/dJMcahb1V8X/T19YyvxBbCNfHdXTCphJw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9DikE/dJMcahb1V8X/T19YyvxBbCNfHdXTCphJw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9DikE/dJMcahb1V8X/T19YyvxBbCNfHdXTCphJw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9DikE%2FdJMcahb1V8X%2FT19YyvxBbCNfHdXTCphJw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;568&quot; height=&quot;307&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;678&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1506&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2uB4H/dJMcafeejZm/JYvoPviJdj1d8JzGCZ7JA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2uB4H/dJMcafeejZm/JYvoPviJdj1d8JzGCZ7JA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2uB4H/dJMcafeejZm/JYvoPviJdj1d8JzGCZ7JA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2uB4H%2FdJMcafeejZm%2FJYvoPviJdj1d8JzGCZ7JA0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;816&quot; height=&quot;167&quot; data-origin-width=&quot;1506&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래쪽이 자식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위쪽이 부모 프로세스&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 과정을 거친다고 하는데 사실 잘 이해가 안간다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시로 살펴보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OS 입장에서는 새로운 프로그램을 위해 새로운 프로세스를 생성하는게 복잡하니까&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fork()로 복제본을 생성하고, exec()로 새로운 프로그램으로 변환, 실행 후 자식 종료&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 그동안 부모 프로세스는 wait&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 부모 프로세스가 wait 하지 않고 종료해버리면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자식 프로세스는 고아 프로세스가 되고, 그 상태로 계속 남아있다면 zombie process&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 address space도 복제한다고 하는데,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 아직 설명이 없다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 가상메모리와 관련된 내용은 뒤에서 나올 것 같다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;process들은 기본적으로 독립적이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 cooperating 즉 데이터를 공유하거나 주고받을 때 문제가 생기는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 IPC라고 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Inter-process communication&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 해결하기 위해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- shared memory&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- message passing&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두가지 방법을 사용할 수 있다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;741&quot; data-origin-height=&quot;417&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eHItxo/dJMcag5h3BI/7fIOsdK4RbUPt2oSzypUlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eHItxo/dJMcag5h3BI/7fIOsdK4RbUPt2oSzypUlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eHItxo/dJMcag5h3BI/7fIOsdK4RbUPt2oSzypUlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeHItxo%2FdJMcag5h3BI%2F7fIOsdK4RbUPt2oSzypUlK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;741&quot; height=&quot;417&quot; data-origin-width=&quot;741&quot; data-origin-height=&quot;417&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a가 shared memory&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;b가 message passing을 나타낸 그림이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;생산자 - 소비자 문제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항상 나오는 문제인데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제되는 지점은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;버퍼가 가득 찼을 때&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;생산자가 또 넣으려고 하면?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;버퍼가 비었을 때&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;소비자가 꺼내려고 하면?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;동시에 접근&lt;/b&gt;하면 데이터 꼬임&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해 a 방법이 buffer 버퍼를&lt;span&gt;&amp;nbsp;&lt;/span&gt;shared memory로 사용하면 된다는거다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;producer는 버퍼가 가득 찼을 때 버퍼에 데이터를 채우는걸 멈추고 기다리면 되고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;consumer는 버퍼가 비었을 때 버퍼에서 데이터를 가져오는걸 멈추고 기다리면 된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 버퍼를 공유 메모리로 사용하면 될 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이때 동작은 time sharing 즉 concurrently 개념으로 생각하면 된다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;shared memory 방식의 문제점도 존재한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 프로그램을 짜는 사람이 자체적으로 이를 해결해야한다는 문제점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이래서 나오는게 message passing 방식인데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OS 자체적으로 shared memory를 관리하고 이때 발생하는 동기화 문제를 관리하는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 message passing을 위한 api를 제공해 주는 개념이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;send(message)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;receive(message)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 나오는 내용이 여기에 속한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 message passing을 할때도&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 생산자 소비자가 직접적으로 커뮤니케이트 할것인지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 동기적으로 / 비동기적으로 커뮤니케이트 할것인지에 대한 내용이 나온다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 전문적으로 표현하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메일박스 (port)를 사용한&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- direct / indirect 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동기적 / 비동기적인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- blocking IO / non-blocking io&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 표준화한 것이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Shared memory는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;POSIX&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Message Passing에서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Pipes&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/OS</category>
      <author>grammiboii</author>
      <guid isPermaLink="true">https://gothax.tistory.com/77</guid>
      <comments>https://gothax.tistory.com/77#entry77comment</comments>
      <pubDate>Wed, 7 Jan 2026 00:33:48 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA] 알고리즘 고득점 kit dfs/bfs</title>
      <link>https://gothax.tistory.com/67</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타겟 넘버&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 기본적인 dfs bfs&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 dfs&lt;/p&gt;
&lt;pre id=&quot;code_1762536249990&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    
    int answer = 0;
    
    public int solution(int[] numbers, int target) {
        
        dfs(numbers, target, 0, 0);
        
        return answer;
    }
    
    private void dfs(int[]numbers, int target, int index, int sum){
        
        if(index == numbers.length){
            
            if(target == sum){
                answer++;
            }
            
            return;
        }
             
        dfs(numbers, target, index+1, sum + numbers[index]);
        dfs(numbers, target, index+1, sum - numbers[index]);
        
    }
    
    
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dfs를 클래스 변수 안쓰고&lt;/p&gt;
&lt;pre id=&quot;code_1762536832668&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    public int solution(int[] numbers, int target) {
        return dfs(numbers, target, 0, 0);
    }
    
    private int dfs(int[] numbers, int target, int index, int sum) {
        if(numbers.length == index){
            if(target == sum){
                return 1;
            }
            return 0;
        }
        
        return dfs(numbers, target, index + 1, sum + numbers[index]) + 
            dfs(numbers, target, index + 1, sum - numbers[index]);
    }
    
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬때 그대로 풀었는데 이렇게 풀면 메모이제이션이 가능하다는 장점이 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dfs 파람에 따라 리턴 값이 정해져 있기 때문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 index, sum이 같은 경우라면 return 값이 같을 것이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴땐 클래스 변수로 hashmap 선언해서 key, value로 저장해놓기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게임맵 최단거리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 그래프 bfs&lt;/p&gt;
&lt;pre id=&quot;code_1762538927315&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    public int solution(int[][] maps) {
        int[] dx = {1, -1, 0, 0};
        int[] dy = {0, 0, 1, -1};
        
        int answer = 0;
        
        int n = maps.length;
        int m = maps[0].length;
        
        Queue&amp;lt;int[]&amp;gt; q = new ArrayDeque&amp;lt;&amp;gt;();
        boolean [][] visited = new boolean[n][m];
        
        q.add(new int[] {0, 0, 1});
        visited[0][0] = true;
        
        
        while(!q.isEmpty()) {
            int[] polled = q.poll();
            int x = polled[0];
            int y = polled[1];
            int move = polled[2];
            
            if(x==n-1 &amp;amp;&amp;amp; y==m-1) {
                return move;
            }
            
            for(int i=0; i&amp;lt;4; i++) {
                int nx = x + dx[i];
                int ny = y + dy[i];
                
                if(0 &amp;lt;= nx &amp;amp;&amp;amp; nx &amp;lt; n &amp;amp;&amp;amp; 0&amp;lt;= ny &amp;amp;&amp;amp; ny &amp;lt; m) {
                    if(maps[nx][ny] == 1 &amp;amp;&amp;amp; visited[nx][ny] == false ) {
                        q.add(new int[] {nx, ny, move+1});
                        visited[nx][ny] = true;
                    }
                }
                
            }
            
            
        }
        
        return -1;
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>ALGORITHM</category>
      <author>grammiboii</author>
      <guid isPermaLink="true">https://gothax.tistory.com/67</guid>
      <comments>https://gothax.tistory.com/67#entry67comment</comments>
      <pubDate>Tue, 11 Nov 2025 17:17:35 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA] 알고리즘 고득점 kit 스택 / 큐 + 정렬</title>
      <link>https://gothax.tistory.com/66</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 오랜만에 자바다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정렬&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 들어가기 전에 자바 정렬 정리&lt;/p&gt;
&lt;pre id=&quot;code_1762436725916&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 배열 오름차순
Arrays.sort(arr);

// 배열 내림차순 (객체만)
Arrays.sort(arr, Collections.reverseOrder());

// 배열 커스텀 정렬
Arrays.sort(arr, (a, b) -&amp;gt; a - b);

// 두개 key로
Arrays.sort(arr, (a, b) -&amp;gt; {
		if (a[0] == b[0]) return a[1]-b[1]
        return a[0] - b[0]
	}
);


// 리스트 오름차순
Collections.sort(list);
list.sort(Comparator.naturalOrder());

// 리스트 내림차순
Collections.sort(list, Collections.reverseOrder());
list.sort(Comparator.reverseOrder());

// 2차원 배열
Arrays.sort(arr, (a, b) -&amp;gt; a[0] - b[0]);

// 문자열 길이순
Arrays.sort(arr, (a, b) -&amp;gt; a.length() - b.length());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;K번째 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42748?language=java&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/42748?language=java&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 정렬 문제 + substring&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기억할 포인트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 배열 자르기는 Arrays.copyOfRange(arr, i, j)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;-&amp;gt; i부터 j-1까지 복사&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 정렬 Arrays.sort(arr);&lt;/p&gt;
&lt;pre id=&quot;code_1762436261226&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    public int[] solution(int[] array, int[][] commands) {
        int[] answer = new int[commands.length];
        
        
        for(int idx=0; idx&amp;lt;commands.length; idx++){
            int i = commands[idx][0];
            int j = commands[idx][1];
            int k = commands[idx][2];
            
            int[] copy = Arrays.copyOfRange(array, i-1, j);
            Arrays.sort(copy);
            answer[idx] = copy[k-1];
        }
        
        
        return answer;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 큰 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42746?language=java&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/42746?language=java&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;붙이면 더 큰수를 찾는문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열로 더했을 때 뭐가 더 큰지 비교하면 된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기억할 포인트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- int 배열을 String 배열로 바꿔주는 부분&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;String.valueOf(num);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 문자열로 비교할때 Comparator 사용하는 부분&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;Arrays.sort(arr, (a, b) -&amp;gt; (b+a).compareTo(a+b));&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1762437276581&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    public String solution(int[] numbers) {
        String answer = &quot;&quot;;
        
        String[] arr = new String[numbers.length];
        for(int i=0; i&amp;lt;numbers.length; i++){
            arr[i] = String.valueOf(numbers[i]);
        }
        
        
        Arrays.sort(arr, (a,b) -&amp;gt; (b+a).compareTo(a+b));
        
        
        if(arr[0].equals(&quot;0&quot;)) return &quot;0&quot;;

        
        StringBuilder sb = new StringBuilder();
        for(String el : arr) {
            sb.append(el);
        }
        
        
        return sb.toString();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스택 큐&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 숫자는 싫어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/12906&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/12906&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기억할 포인트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- list -&amp;gt; array&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;answer.stream().mapToInt(Integer::toIntValue).toArray();&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기억 안나면 배열 생성하고 하나씩 넣어주기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;int[] arrayAnswer = new int[answer.size()];&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;for문 돌면서 arrayAnswer[i] = answer.get(i);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1762431664724&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

public class Solution {
    public int[] solution(int []arr) {
        ArrayList&amp;lt;Integer&amp;gt; answer = new ArrayList&amp;lt;&amp;gt;();
        
        Integer prev = null;
        for(int el : arr) {
            if(prev == null) {
                answer.add(el);
                prev = el;
            }
            
            if (prev != null) {
                if(prev != el){
                    answer.add(el);
                }
                prev = el;
            }
        }
        // return answer.stream().mapToInt(Integer::intValue).toArray();
        
        int[] returnAnswer = new int[answer.size()];
        for (int i=0; i&amp;lt;answer.size(); i++){
            returnAnswer[i] = answer.get(i);
        }
            
            
        return returnAnswer;
    }
    
    public void print(Object o){
        System.out.println(o);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기능개발&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42586&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/42586&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큐로도 할 수 있을 것 같은데 인덱스로 했다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1762433956675&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    public int[] solution(int[] progresses, int[] speeds) {
        
        List&amp;lt;Integer&amp;gt; answer = new ArrayList&amp;lt;&amp;gt;();
        
        int date = 1;
        int complete = 0;
        
        for(int i=0; i&amp;lt;progresses.length; i++){
            int progress = progresses[i];
            int speed = speeds[i];
            
            int finishDate = dayLeft(progress, speed);
            
            // 남았을때 이전꺼 기록, 초기화, date 움직이기
            if(finishDate &amp;gt; date){
                
                if(complete != 0){
                    answer.add(complete);
                    complete = 0;
                }
                
                date = finishDate;
                complete++;
                
                continue;
            }
            // 이미 처리 완료이면 date 그대로 complete++
            complete++;
        }
        if(complete != 0){
            answer.add(complete);
        }
        
        
        return answer.stream().mapToInt(Integer::intValue).toArray();
    }
    
    public int dayLeft(int progress, int speed){
        int result = (100 - progress) / speed;
        int left = (100 - progress) % speed;
        if (left &amp;gt; 0){
            result++;
        }
        return result;
    }
    
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42587&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/42587&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;os 프로세스 우선순위 실행을 구현해보는 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기억할 포인트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 큐2개를 쓰는 방법이 처음에 잘 생각이 안났다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금보니 우선순위큐에는 인덱스를 저장할 필요는 없는 것 같다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;pq에 배열을 안넣고 Integer를 넣어주면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;Collections.reverseOrder()로 Comparator를 넣어줄 수 있어서 더 간결하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 우선순위큐는 pq.peek()하면서 꺼내지 않기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1762439528130&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;


class Solution {
    public int solution(int[] priorities, int location) {
        int answer = 0;
        
        Queue&amp;lt;int[]&amp;gt; q = new ArrayDeque&amp;lt;&amp;gt;();
        Queue&amp;lt;int[]&amp;gt; pq = new PriorityQueue&amp;lt;&amp;gt;((a,b) -&amp;gt; b[1] - a[1]);
        
        for(int i=0; i&amp;lt;priorities.length; i++){
            q.add(new int[] {i, priorities[i]});
            pq.add(new int[] {i, priorities[i]});
        }
        
        while (! q.isEmpty()){
            int[] current = q.poll();
            
            if(current[1] &amp;lt; pq.peek()[1]){
                q.add(current);
            } else{
                pq.poll();
                // 실행
                answer++;
                if (current[0] == location) return answer;
            }
            
        }
        
        return answer;
    }
    
    public void print(Object o){
        System.out.println(o);
    }
    
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>ALGORITHM</category>
      <author>grammiboii</author>
      <guid isPermaLink="true">https://gothax.tistory.com/66</guid>
      <comments>https://gothax.tistory.com/66#entry66comment</comments>
      <pubDate>Thu, 6 Nov 2025 22:59:04 +0900</pubDate>
    </item>
    <item>
      <title>[PYTHON] 프로그래머스 고득점 kit</title>
      <link>https://gothax.tistory.com/64</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정렬&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;k 번째 큰 수&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42748&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/42748&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉬운문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기억할 포인트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 파이썬에서는 substring 사용할때 슬라이싱 array[i:j]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; i 인덱스부터 j-1까지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제에서는 인덱스+1 되어 있어서 i-1 : j&lt;/p&gt;
&lt;pre id=&quot;code_1761300932493&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(array, commands):
    answer = []
    for i, j, k in commands:
        
        substring = array[i-1:j]
        substring.sort()
        answer.append(substring[k-1])
    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가장 큰 수&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42746&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/42746&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉬운 정렬 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기억할 포인트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sort에서 key를 사용할때 자바처럼 매개변수 2개가 안들어간다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용하려면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- from functools import cmp_to_key&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1761300883872&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from functools import cmp_to_key

def solution(numbers):
    
    def comparator(x, y):
        if x + y &amp;gt; y + x:
            return -1
        elif x + y &amp;lt; y + x:
            return 1
        else:
            return 0
        

        
    numbers = list(map(str, numbers))
    numbers.sort(key = cmp_to_key(comparator))
    
    answer =  ''.join(numbers)
    return '0' if answer[0] == '0' else answer&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막에 0000 인 경우를 위해 예외처리해야하는 함정이 있었다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;H-index&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42747&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/42747&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생각해내기가 어렵다.,, 시험시간에 이런 생각을 할 수 있을까?&lt;/p&gt;
&lt;pre id=&quot;code_1761302360579&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(citations):
    
    citations.sort(reverse=True)
    h = 0
    
    for i, citation in enumerate(citations):
        if citation &amp;gt;= i+1:
            h = i+1
        else:
            break
    return h&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DFS / BFS&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;타겟 넘버&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/43165?language=python3&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/43165?language=python3&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기억할 포인트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;from functools import lru_cache&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모이제이션 캐싱 풀이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dfs 풀이&lt;/p&gt;
&lt;pre id=&quot;code_1761308967913&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(numbers, target):
    answer = 0
    
    def dfs(index, current_sum):
        nonlocal answer
        
        if len(numbers) == index:
            if current_sum == target:
                answer += 1
            return
        
        dfs(index+1, current_sum + numbers[index])
        dfs(index+1, current_sum - numbers[index])
    
    dfs(0,0)
    
    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;count를 반환하는 dfs 풀이&lt;/p&gt;
&lt;pre id=&quot;code_1761309253924&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(numbers, target):
    
    def dfs(index, currnet_sum):
        
        if index == len(numbers):
            if currnet_sum == target:
                return 1
            return 0
        
        count = 0
        
        count += dfs(index+1, currnet_sum + numbers[index])
        count += dfs(index+1, currnet_sum - numbers[index])
        
        return count
    
    return dfs(0, 0)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bfs 풀이&lt;/p&gt;
&lt;pre id=&quot;code_1761309567576&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import deque

def solution(numbers, target):
    answer = 0
    
    q = deque([(0,0)])
    
    while q:
        index, current_sum = q.popleft()
        
        if index == len(numbers):
            if current_sum == target:
                answer += 1
            continue
        
        q.append((index + 1, current_sum + numbers[index]))
        q.append((index + 1, current_sum - numbers[index]))
    
    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;lru cache 적용 풀이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신 캐싱을 적용하기 때문에 중간 로직에 answer+=1 하는 로직은 사용하면 안되고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dfs return 값으로 계산하는 방식을 사용해야한다&lt;/p&gt;
&lt;pre id=&quot;code_1761310578734&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from functools import lru_cache

def solution(numbers, target):
    
    @lru_cache(maxsize = None)
    def dfs(index, current_sum):
        if len(numbers) == index:
            if target == current_sum:
                return 1
            return 0
        
        count = 0
        
        count += dfs(index + 1, current_sum + numbers[index])
        count += dfs(index + 1, current_sum - numbers[index])
        
        return count
    
    
    return dfs(0, 0)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;네트워크&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/43162&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/43162&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 섬찾기 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;visited를 배열로 많이 하는데 여기서는 set으로 해봤다&lt;/p&gt;
&lt;pre id=&quot;code_1761351917111&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import defaultdict

def solution(n, computers):
    answer = 0
    dict = defaultdict(list)
    for i, computer in enumerate(computers):
          for j, c in enumerate(computer):
                if i != j and c == 1:                    
                    dict[i].append(j)
        
    visited = set()
    
    def dfs(index):
        nonlocal answer
        
        visited.add(index)
        for next in dict[index]:
            if next not in visited:
                dfs(next)
    
    for i in range(n):
        if i not in visited:
            answer += 1
            dfs(i)
    
    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;게임맵 최단거리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/1844?language=python3&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/1844?language=python3&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오랜만에 파이썬으로 하니 굉장히 쉽다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 BFS&lt;/p&gt;
&lt;pre id=&quot;code_1761355377271&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import deque

def solution(maps):
    answer = 0
    n, m = len(maps), len(maps[0])
    
    q = deque([(0, 0, 1)])
    directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
    
    visited = [[False]*m for _ in range (n)]
    visited[0][0] = True
    
    while q:
        x, y, move = q.popleft()
        
        if x == n-1 and y == m-1:
            return move
        
        for dx, dy in directions:
            xx, yy = x + dx, y + dy
            if 0 &amp;lt;= xx &amp;lt; n and 0 &amp;lt;= yy &amp;lt; m and maps[xx][yy] == 1 and visited[xx][yy] == False:
                visited[xx][yy] = True
                q.append((xx, yy, move+1))
        
    return -1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단어 변환&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기억할 포인트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- zip&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 풀이 - 오답&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;can transform 메서드가 틀렸다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(위치를 생각하지 않아서)&lt;/p&gt;
&lt;pre id=&quot;code_1761356682153&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import deque

def solution(begin, target, words):
    
    # a에서 b로
    def can_transform(a, b):
        return len(set(a) - set(b)) == 1
    
        
    if target not in words:
        return 0
    
    q = deque([(begin, 0)])
    visited = set([begin])
    
    while q:
        current, count = q.popleft()
        
        if current == target:
            return count
        
        for word in words:
            if word not in visited and can_transform(current, word):
                visited.add(word)
                q.append((word, count + 1))
        
    return 0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;zip을 사용했는데 그냥 index로 계산해도 된다&lt;/p&gt;
&lt;pre id=&quot;code_1761357029603&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import deque

def solution(begin, target, words):
    
    # a에서 b로
    def can_transform(a, b):
        diff_count = 0
        for c1, c2 in zip(a, b):
            if c1 != c2:
                diff_count += 1
        return diff_count == 1
    
        
    if target not in words:
        return 0
    
    q = deque([(begin, 0)])
    visited = set([begin])
    
    while q:
        current, count = q.popleft()
        
        if current == target:
            return count
        
        for word in words:
            if word not in visited and can_transform(current, word):
                visited.add(word)
                q.append((word, count + 1))
        
    return 0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;zip을 살펴보면 리스트 두개 OR 문자열 두개를 나란히 묶어주는 메서드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘의 길이가 다르면 짧은 쪽에 맞춰진다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응용해서 파이썬식 좀더 간결하게&lt;/p&gt;
&lt;pre id=&quot;code_1761357264320&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    def can_transform(a, b):
        return sum(c1 != c2 for c1, c2 in zip(a, b)) == 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시험시간에 기억 안나면 그냥 인덱스로 빨리 풀자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;여행경로&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어렵다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 아이디어는 막다른 길까지 도달해야한다는 점이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;[[&quot;ICN&quot;, &quot;JFK&quot;], [&quot;HND&quot;, &quot;IAD&quot;], [&quot;JFK&quot;, &quot;HND&quot;]]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;ticket일때&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;icn -&amp;gt; jfk&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재귀&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;current jfk&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;jfk -&amp;gt; hnd&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재귀&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;current hnd&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hnd -&amp;gt; iad&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재귀&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;current iad&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 딕셔너리가 비어있기 때문에 while문으로 들어가지 않는다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 current인 aid를 answer에 append&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;탈출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hnd를 append&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;jfk append&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;icn append&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리스트를 뒤집으면 경로가 나온다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1761362135691&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import heapq
from collections import defaultdict

def solution(tickets):

    dict = defaultdict(list)
    
    for f, t in tickets:
        heapq.heappush(dict[f], t)
    
    answer = []
    
    def dfs(current):
        while dict[current]:
            next = heapq.heappop(dict[current])
            dfs(next)
        
        answer.append(current)
        

    dfs(&quot;ICN&quot;)
    return answer[::-1]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>ALGORITHM</category>
      <author>grammiboii</author>
      <guid isPermaLink="true">https://gothax.tistory.com/64</guid>
      <comments>https://gothax.tistory.com/64#entry64comment</comments>
      <pubDate>Fri, 24 Oct 2025 21:29:39 +0900</pubDate>
    </item>
    <item>
      <title>[JVM 밑바닥까지 파헤치기] 2장 자바 메모리 영역과 오버플로우</title>
      <link>https://gothax.tistory.com/53</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 스레드, 동시성 강의와 책을 병행하려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;런타임 데이터 영역&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://gothax.tistory.com/48&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://gothax.tistory.com/48&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의에서 본 자바 메모리 영역을 이렇게 봤었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책을 읽어보니 조금 더 자세하게 나와있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;247&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qU0Ib/btsPUjB36ZT/hTDLk9mwl1jqg4EktVuPJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qU0Ib/btsPUjB36ZT/hTDLk9mwl1jqg4EktVuPJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qU0Ib/btsPUjB36ZT/hTDLk9mwl1jqg4EktVuPJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqU0Ib%2FbtsPUjB36ZT%2FhTDLk9mwl1jqg4EktVuPJK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;684&quot; height=&quot;247&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;247&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;951&quot; data-origin-height=&quot;718&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KQcGG/btsPUUIKOKK/r8IikJYpivrFc6KAkFuiKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KQcGG/btsPUUIKOKK/r8IikJYpivrFc6KAkFuiKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KQcGG/btsPUUIKOKK/r8IikJYpivrFc6KAkFuiKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKQcGG%2FbtsPUUIKOKK%2Fr8IikJYpivrFc6KAkFuiKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;735&quot; height=&quot;555&quot; data-origin-width=&quot;951&quot; data-origin-height=&quot;718&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;프로그램 카운터 (Program Counter Registry)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이부분이 위 그림에 안나와 있었다 편의상 생략된듯&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pc register는 작은 메모리 영역으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;현재 실행중인 스레드의 바이트코드 줄 번호 표시기&lt;/b&gt;라고 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택 영역에서 메서드를 실행할때마다 스택 프레임을 쌓고, 코드를 한줄한줄 실행한다고 했던거 기억이 나는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 그 한줄한줄 실행할때 어디인지를 기록하는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀더 이론적으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바이트코드 인터프리터가 이 카운터의 값을 바꿔 다음 실행할 명령어를 선택하는 식으로 작동한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 이용해 프로그램의 제어 흐름, 분기, 순환, 점프 등을 표현한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예외처리, 스레드 복원&lt;/b&gt;같은 기본 기능이 이 표시기를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연히 스레드별로 분리되어 있다. (&lt;b&gt;스레드 프라이빗 메모리&lt;/b&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유일하게 OOM out of memory 예외 조건이 명시되지 않은 영역이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;스택 영역 (Stack)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복습할겸 다시 적어보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스레드 별 하나의 실행 스택이 생성되고 (&lt;b&gt;스레드 수 만큼 스택이 생성된다&lt;/b&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 메서드를 실행하는 &lt;b&gt;스레드의 메모리 모델&lt;/b&gt;을 설명해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 메서드가 호출될 때마다 가상머신이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스택 프레임&lt;/b&gt;을 생성해 &lt;b&gt;지역변수 테이블, 피연산자 스택, 동적 링크, 메서드 반환값&lt;/b&gt;등의 정보를 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 스택프레임을 스택 영역에 push, pop을 반복&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지역 변수 테이블에는 컴파일 타임에 알 수 있는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 타입, 객체 참조, 반환 주소 타입을 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 값들을 저장하는 공간들을&amp;nbsp;&lt;b&gt;지역 변수 슬롯&lt;/b&gt;이라고 한다. (일반적으로 32bit)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 컴파일 과정에서 할당되고 메서드 실행중에 절대 변하지 않는다. (슬롯 개수)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;&amp;lt;자바 가상 머신 명세&amp;gt;&amp;gt;에서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택 메모리 영역에서는 두가지 예외를 던질 수 있도록 정의했다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. StackOverFlow&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 요청한 스택 깊이가 가상머신이 허용하는 깊이보다 깊을때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. OOM&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;&amp;nbsp; &amp;nbsp; 현재의 핫스팟 가상 머신은 스택 용량을 동적으로 늘리지 못하기 때문에 던질 일이 없다고 한다&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;&amp;nbsp; &amp;nbsp; 이거 뭔말인지 모르겠다&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마찬가지로 스레드별로 분리되어 있다. (&lt;b&gt;스레드 프라이빗 메모리&lt;/b&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;힙 영역 (Heap)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;객체 인스턴스를 저장한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 인스턴스와 배열을 생성하는데&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에는 &quot;거의&quot; 모든이라고 나와 있다. 구현 관점에서 자바가 발전하며 스택 할당과 스칼라 치환 최적화 방식이 살짝 달라져서라고 하는데, 뭔말인지 잘 모르겠다. 일단 모든 인스턴스라고 이해하고 넘어가자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GC가 관리하는 메모리 영역이어서 &lt;b&gt;GC 힙&lt;/b&gt;이라고도 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 할당 효율을 높이고자 스레드 로컬 할당 버퍼 여러개로 나뉜다고 한다. 즉 메모리 회수와 할당을 더 빠르게 하기 위함이라고 하는데 이건 뒤에 나오는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 힙은 크기를 고정할수도, 확장할수도 있게 구현할 수 있다. 주류로 사용되는 가상 머신은 대부분 확장 가능한 형태라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이로 인해 새로운 인스턴스를 위한 힙 영역이 부족하고, 힙을 확장할 수 없을때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;OOM 예외를&lt;/b&gt; 던진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스를 참조해야하니까 힙 영역은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;모든 스레드가 공유한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;메서드 영역 (Method)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상 머신이 읽은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입정보, 상수, static 변수, 코드 캐시등을 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 강의에서 봤던 그림에는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스 정보, static 변수, 상수풀을 저장한다고 되어 있는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입 정보 + 코드 캐시 -&amp;gt; 클래스 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;static 변수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 생각하면 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 캐시를 좀더 자세하게&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JIT 컴파일러가 컴파일한 코드라고 이해하면 된다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힙과 마찬가지로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;모든 스레드가 공유한다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>SUMMARY/JAVA</category>
      <author>grammiboii</author>
      <guid isPermaLink="true">https://gothax.tistory.com/53</guid>
      <comments>https://gothax.tistory.com/53#entry53comment</comments>
      <pubDate>Fri, 15 Aug 2025 17:51:52 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA 고급1] 3. 스레드 제어와 생명주기 1</title>
      <link>https://gothax.tistory.com/49</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스레드 생명 주기&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1346&quot; data-origin-height=&quot;838&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5zSE6/btsP26i6xHe/MqOkbF1nLrNN1JRKkBENNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5zSE6/btsP26i6xHe/MqOkbF1nLrNN1JRKkBENNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5zSE6/btsP26i6xHe/MqOkbF1nLrNN1JRKkBENNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5zSE6%2FbtsP26i6xHe%2FMqOkbF1nLrNN1JRKkBENNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1346&quot; height=&quot;838&quot; data-origin-width=&quot;1346&quot; data-origin-height=&quot;838&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OS에서도 많이 본 그림인데 하나씩 살펴보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- New&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 스레드가 생성되었지만 시작되지 않은 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; start 메서드를 호출하지 않은 상태이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Runnable&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 스레드가 실행중이거나 실행될 준비가 된 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; start 메서드를 호출하면 해당 상태로 들어간다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; OS 스케줄러가 각 스레드에 CPU 시간을 할당해 실행하기 때문에 (time waiting)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; Runnable 상태 스레드는 실행 대기열에 포함되었다가 차례로 CPU에서 실행된다. - 자바에서는 이를 구분할 수 없다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 일시 중지 상태들&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; - &lt;b&gt;Blocked&lt;/b&gt; : 스레드가 락을 기다리는 상태 (뒤에서 synchronized와 모니터 락을 배운다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; - &lt;b&gt;Waiting&lt;/b&gt; : 스레드가 무기한으로 다른 스레드의 작업을 기다리는 상태 (wait, join, notify, notifyAll)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; - &lt;b&gt;Timed Waiting&lt;/b&gt; : 스레드가 일정 기간동안 다른 스레드의 작업을 기다리는 상태 (sleep(ms), wait(ms), join(ms))&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;Terminated&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 스레드의 실행이 완료된 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;join 시작&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;597&quot; data-origin-height=&quot;563&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blYqD9/btsPRvaUbCL/GtTj7UcUa12ZaB7ooQHHJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blYqD9/btsPRvaUbCL/GtTj7UcUa12ZaB7ooQHHJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blYqD9/btsPRvaUbCL/GtTj7UcUa12ZaB7ooQHHJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblYqD9%2FbtsPRvaUbCL%2FGtTj7UcUa12ZaB7ooQHHJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;597&quot; height=&quot;563&quot; data-origin-width=&quot;597&quot; data-origin-height=&quot;563&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main 스레드는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;thread1, thread2에게 Job을 시키고 자신의 코드를 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;thread1, thread2가 종료되고 main 스레드를 종료하려면 어떻게 해야할까? -&amp;gt; 이때 join이 필요하다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 상황은 예를 들어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;thread1, thread2에 어떤 작업을 지시하고 이 결과값을 main 스레드에서 받아 사용할때 필요하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;join이 필요한 상황 예제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1~100까지 숫자를 더하는 작업을 수행하는데 이걸 병렬로 돌리기 위해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1~50을 더하는 작업을 thread-1에게 시키고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;51~100까지 더하는 작업을 thread-2에게 시킨다고 하자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 확실히 결과를 보기 위해 thread-1, thread-2에서 수행하는 작업이 2초 걸린다고 가정하자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;578&quot; data-origin-height=&quot;627&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TdDHp/btsPPDIepO0/C5D00bKlRdR5F2pziSKiq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TdDHp/btsPPDIepO0/C5D00bKlRdR5F2pziSKiq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TdDHp/btsPPDIepO0/C5D00bKlRdR5F2pziSKiq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTdDHp%2FbtsPPDIepO0%2FC5D00bKlRdR5F2pziSKiq1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;578&quot; height=&quot;627&quot; data-origin-width=&quot;578&quot; data-origin-height=&quot;627&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;525&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqIGhm/btsPQuXTSkI/KxDtmmXn7dlxxVogYaus0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqIGhm/btsPQuXTSkI/KxDtmmXn7dlxxVogYaus0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqIGhm/btsPQuXTSkI/KxDtmmXn7dlxxVogYaus0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqIGhm%2FbtsPQuXTSkI%2FKxDtmmXn7dlxxVogYaus0k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;525&quot; height=&quot;500&quot; data-origin-width=&quot;525&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 결과는 어떻게 나올까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;423&quot; data-origin-height=&quot;271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DPWrR/btsPPE8erMD/kkiOt4yKMkf0WyAZZgtThk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DPWrR/btsPPE8erMD/kkiOt4yKMkf0WyAZZgtThk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DPWrR/btsPPE8erMD/kkiOt4yKMkf0WyAZZgtThk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDPWrR%2FbtsPPE8erMD%2FkkiOt4yKMkf0WyAZZgtThk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;423&quot; height=&quot;271&quot; data-origin-width=&quot;423&quot; data-origin-height=&quot;271&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main 스레드가 thread-1, thread-2의 작업을 기다리지 않기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과값이어야 하는 5050이 나오지 않고 0이라는 결과가 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>SUMMARY/JAVA</category>
      <author>grammiboii</author>
      <guid isPermaLink="true">https://gothax.tistory.com/49</guid>
      <comments>https://gothax.tistory.com/49#entry49comment</comments>
      <pubDate>Wed, 13 Aug 2025 01:07:01 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA 고급1] 2. 스레드의 생성과 실행</title>
      <link>https://gothax.tistory.com/48</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Java 메모리 구조&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;247&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XU4hj/btsPNJHfhld/E6pgS5ykz8TAWZre6aRGv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XU4hj/btsPNJHfhld/E6pgS5ykz8TAWZre6aRGv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XU4hj/btsPNJHfhld/E6pgS5ykz8TAWZre6aRGv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXU4hj%2FbtsPNJHfhld%2FE6pgS5ykz8TAWZre6aRGv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;684&quot; height=&quot;247&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;247&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java 메모리는 3가지 영역으로 구성되어 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 메서드 영역 Method Area&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 프로그램을 실행하는데 필요한 공통 데이터를 관리한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; 그러므로 프로그램의 모든 영역에서 공유&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 안에 있는 3가지는 각각&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 클래스 정보 : 클래스 실행 코드, 필드, 메서드, 생성자등 모든 실행코드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; static 영역 : static 변수 보관&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 런타임 상수 풀 : 공통 리터럴 상수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 스택 영역 Stack Area&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 스레드 별 하나의 실행 스택이 생성된다 (&lt;b&gt;스레드 수 만큼 스택이 생성된다&lt;/b&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 네모칸 하나가 스택 프레임이고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 지역 변수, 중간 연산 결과, 메서드 호출 정보를 포함한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 메서드를 호출할 때 마다 하나의 스택 프레임이 쌓이고, 메서드가 종료되면 해당 스택 프레임이 제거된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 힙 영역 Heap Area&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/b&gt;객체(인스턴스), 배열이 생성되는 영역&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; GC가 이루어지는 주요 영역&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/b&gt;더이상 참조되지 않는 객체는 GC에 의해 제거됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스레드 생성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스레드를 직접 만들때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Thread 클래스를 상속받는 법, Runnable 인터페이스를 구현하는 방법이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Thread 상속&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;213&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XVuaA/btsPNpba35C/PIzxXGdCIDFURDcWiPXuhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XVuaA/btsPNpba35C/PIzxXGdCIDFURDcWiPXuhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XVuaA/btsPNpba35C/PIzxXGdCIDFURDcWiPXuhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXVuaA%2FbtsPNpba35C%2FPIzxXGdCIDFURDcWiPXuhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;884&quot; height=&quot;213&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;213&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상속하고 run 메서드를 override해주면 된다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MhXf4/btsPMJuqs9A/mP4Oq1mzfvlClV6eig2n5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MhXf4/btsPMJuqs9A/mP4Oq1mzfvlClV6eig2n5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MhXf4/btsPMJuqs9A/mP4Oq1mzfvlClV6eig2n5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMhXf4%2FbtsPMJuqs9A%2FmP4Oq1mzfvlClV6eig2n5K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;724&quot; height=&quot;554&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;554&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의할 점은 오버라이드한 run 메서드를 호출하는 것이 아니라&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;start 메서드를 실행해야한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이유는 뒤에서&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;390&quot; data-origin-height=&quot;116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7hLf2/btsPLmfNS9I/urFlkR3bHM9BS4m8qNmr80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7hLf2/btsPLmfNS9I/urFlkR3bHM9BS4m8qNmr80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7hLf2/btsPLmfNS9I/urFlkR3bHM9BS4m8qNmr80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7hLf2%2FbtsPLmfNS9I%2FurFlkR3bHM9BS4m8qNmr80%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;390&quot; height=&quot;116&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;390&quot; data-origin-height=&quot;116&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;418&quot; data-origin-height=&quot;132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1924o/btsPO45dgpQ/i59NTbol5rzwVrJgE6Y4Bk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1924o/btsPO45dgpQ/i59NTbol5rzwVrJgE6Y4Bk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1924o/btsPO45dgpQ/i59NTbol5rzwVrJgE6Y4Bk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1924o%2FbtsPO45dgpQ%2Fi59NTbol5rzwVrJgE6Y4Bk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;396&quot; height=&quot;125&quot; data-origin-width=&quot;418&quot; data-origin-height=&quot;132&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행할때마다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 만든 스레드 내부에서 실행되는 Thread-0 출력 순서가 달라질 수 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이 이유도 뒤에서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해석해보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;266&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xnRyC/btsPLKHtd4U/pSpivlJvo9b15r786VGFZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xnRyC/btsPLKHtd4U/pSpivlJvo9b15r786VGFZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xnRyC/btsPLKHtd4U/pSpivlJvo9b15r786VGFZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxnRyC%2FbtsPLKHtd4U%2FpSpivlJvo9b15r786VGFZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;551&quot; height=&quot;220&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;266&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스가 실행되기 위해 최소 하나의 스레드가 필요하니&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main 스레드가 시작되고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main 스택 영역이 할당된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;674&quot; data-origin-height=&quot;217&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pwfyL/btsPNbdasU1/19bNepXQ2N5zokKVNkc3N1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pwfyL/btsPNbdasU1/19bNepXQ2N5zokKVNkc3N1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pwfyL/btsPNbdasU1/19bNepXQ2N5zokKVNkc3N1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpwfyL%2FbtsPNbdasU1%2F19bNepXQ2N5zokKVNkc3N1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;615&quot; height=&quot;198&quot; data-origin-width=&quot;674&quot; data-origin-height=&quot;217&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그후 HelloThread 인스턴스를 생성한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그후 start() 메서드를 호출할때&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바가 스레드를 위한 스택 영역을 할당한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면서 Thread-0 스레드가 run() 메서드의 스택 프레임을 스택에 올리고 run()메서드를 시작한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 자세히 보면&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;685&quot; data-origin-height=&quot;358&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwXA0n/btsPMUWQ6CD/tXMG5QHfsV2gLJXUwl2a6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwXA0n/btsPMUWQ6CD/tXMG5QHfsV2gLJXUwl2a6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwXA0n/btsPMUWQ6CD/tXMG5QHfsV2gLJXUwl2a6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwXA0n%2FbtsPMUWQ6CD%2FtXMG5QHfsV2gLJXUwl2a6K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;685&quot; height=&quot;358&quot; data-origin-width=&quot;685&quot; data-origin-height=&quot;358&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의할 점은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;run() 메서드를 실행하는 것은 Thread-0 라는 점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main 스레드는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;start()메서드로 Thread-0 스레드에게 시작하라고 명령을 하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 후 일을 진행하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;--&amp;gt; 이러면 Thread-0에서 실행되는 출력 순서가 달라지는 이유가 이해된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; main 스레드 입장에서는 start로 Thread-0를 부르고 이후, 기다리지 않고 start 메서드를 빠져 나와 출력을 찍은 것이고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 동시에 Thread-0 내부에서는 출력을 수행하니 순서가 달라질 수 있는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 main 스레드와 Thread-0가 &lt;b&gt;동시에&amp;nbsp;&lt;/b&gt;실행되는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;--&amp;gt; 그리고 이로 인해 main 스레드에서 Thread-0 run 메서드가 아닌 start 메서드를 호출해야하는 이유도 이해가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; run을 호출하게 되면 Thread-0에서 run 메서드를 &lt;b&gt;실행하는게 아니라&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/b&gt;main 스레드에서 run 메서드를 실행하게 되는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; 즉, 스택 영역이 하나만 할당되는 것이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 보면&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;596&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p57XL/btsPNndVO45/JnjvcvqVeLgKQ8NLCO0xz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p57XL/btsPNndVO45/JnjvcvqVeLgKQ8NLCO0xz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p57XL/btsPNndVO45/JnjvcvqVeLgKQ8NLCO0xz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp57XL%2FbtsPNndVO45%2FJnjvcvqVeLgKQ8NLCO0xz0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;610&quot; height=&quot;249&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;596&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림으로 보면&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1350&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kMuDK/btsPMW8KAjQ/9xgutch8jOfY97t2nUnPB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kMuDK/btsPMW8KAjQ/9xgutch8jOfY97t2nUnPB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kMuDK/btsPMW8KAjQ/9xgutch8jOfY97t2nUnPB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkMuDK%2FbtsPMW8KAjQ%2F9xgutch8jOfY97t2nUnPB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;602&quot; height=&quot;248&quot; data-origin-width=&quot;1350&quot; data-origin-height=&quot;556&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;사용자 스레드, 데몬 스레드 (user thread, daemon thread)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스레드는 두가지 종류가 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 사용자 스레드 (non-daemon thread)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 프로그램 주요 작업을 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 작업이 완료 될때까지 실행된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 모든 user thread가 종료되면 JVM이 종료된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 데몬 스레드 (daemon thread)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 백그라운드 작업을 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 모든 user thread가 종료되면 daemon thread는 자동으로 종료된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 예를 들어 사용하지 않는 파일이나 메모리를 정리하는 작업을 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JVM이 종료되는 시점에 대해 추가하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 사용자 스레드가 종료될 때까지 기다려야 하므로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 스택 영역이 빌때까지 기다리고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모두 비었다면 그때 종료된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면에 데몬 스레드가 돌아가고 있어도 사용자 스레드가 모두 종료된다면 JVM이 종료된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;daemon thread 예시를 보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1348&quot; data-origin-height=&quot;808&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kM29f/btsPOJHHllP/nbQZRqK0NyhADDTzphrzL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kM29f/btsPOJHHllP/nbQZRqK0NyhADDTzphrzL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kM29f/btsPOJHHllP/nbQZRqK0NyhADDTzphrzL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkM29f%2FbtsPOJHHllP%2FnbQZRqK0NyhADDTzphrzL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;521&quot; height=&quot;312&quot; data-origin-width=&quot;1348&quot; data-origin-height=&quot;808&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1368&quot; data-origin-height=&quot;466&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EXmkI/btsPNffUtg2/em5beUjYhcbOvngKUTrWzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EXmkI/btsPNffUtg2/em5beUjYhcbOvngKUTrWzK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EXmkI/btsPNffUtg2/em5beUjYhcbOvngKUTrWzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEXmkI%2FbtsPNffUtg2%2Fem5beUjYhcbOvngKUTrWzK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;737&quot; height=&quot;251&quot; data-origin-width=&quot;1368&quot; data-origin-height=&quot;466&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKB1fE/btsPOpCg9iq/4qdoZKxDrLyJl2zTcm5zIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKB1fE/btsPOpCg9iq/4qdoZKxDrLyJl2zTcm5zIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKB1fE/btsPOpCg9iq/4qdoZKxDrLyJl2zTcm5zIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKB1fE%2FbtsPOpCg9iq%2F4qdoZKxDrLyJl2zTcm5zIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;514&quot; height=&quot;233&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;284&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데몬 스레드 내부에서 10초 후에 출력을 하도록 설정했는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;daemon thread 내부 run 메서드 출력이 나오지 않고 프로그램이 종료된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Runnable 인터페이스 구현&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서는 Thread 클래스를 상속받아 스레드를 생성했는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 Runnable 인터페이스를 구현해서 스레드를 생성해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실무에서는 보통 이 방법을 사용한다고 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1304&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IyDP3/btsPPXFc5bh/4apUWxQK6UmkKO7f1XdEwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IyDP3/btsPPXFc5bh/4apUWxQK6UmkKO7f1XdEwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IyDP3/btsPPXFc5bh/4apUWxQK6UmkKO7f1XdEwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIyDP3%2FbtsPPXFc5bh%2F4apUWxQK6UmkKO7f1XdEwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1304&quot; height=&quot;600&quot; data-origin-width=&quot;1304&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1404&quot; data-origin-height=&quot;490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/evp53r/btsPL29tqyV/CnG5WNH4o3X3JhjOENSKSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/evp53r/btsPL29tqyV/CnG5WNH4o3X3JhjOENSKSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/evp53r/btsPL29tqyV/CnG5WNH4o3X3JhjOENSKSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fevp53r%2FbtsPL29tqyV%2FCnG5WNH4o3X3JhjOENSKSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1404&quot; height=&quot;490&quot; data-origin-width=&quot;1404&quot; data-origin-height=&quot;490&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;288&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2uKt1/btsPMVotMpb/HQ2CpdrhYGhORSBwAoFIvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2uKt1/btsPMVotMpb/HQ2CpdrhYGhORSBwAoFIvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2uKt1/btsPMVotMpb/HQ2CpdrhYGhORSBwAoFIvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2uKt1%2FbtsPMVotMpb%2FHQ2CpdrhYGhORSBwAoFIvk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;646&quot; height=&quot;288&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;288&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;별로 다른점은 없고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Thread 객체를 바로 생성하는게 아니라&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;runnable 객체를 만들고 thread 객체 생성자 파라미터로 전달한다는게 좀 다르다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분때문에 실무에서 주로 사용한다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면 두가지 이유로 Runnable 인터페이스 구현 방식을 사용하라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 스레드와 실행할 작업을 명확히 분리할 수 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 인터페이스를 사용하는 것이 상속보다 더 유연하고 유지보수 하기 쉽다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>SUMMARY/JAVA</category>
      <author>grammiboii</author>
      <guid isPermaLink="true">https://gothax.tistory.com/48</guid>
      <comments>https://gothax.tistory.com/48#entry48comment</comments>
      <pubDate>Mon, 11 Aug 2025 00:34:50 +0900</pubDate>
    </item>
  </channel>
</rss>