학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문 전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 비공정 모드가 공정 모드가 빠른 이유가 뭔지 자세히 궁금합니다. 비공정 모드에서도 어느 정도 대기큐가 있다고 하셨는데 그 걸 제외하고 공정 모드에서는 대기큐를 사용하면 어떤 스레드가 다음 락을 가져야할 지 알기 때문에 좀 더 빠르지 않나? 라는 생각이 들어서요.. 그리고 비공정 모드에서는 반대로 대기큐를 사용하지 않았기 때문에 공정 모드보다 락 얻기 위한 경합이 일어나서 좀 더 느릴 수 있는거 아닌가..? 싶어서 여쭤봅니다.. 시스템 상황에서 어떻게 비공정 모드가 공정 모드보다 빠른지 이해가 가지 않네요..ㅠㅠ
안녕하세요. 실무에서 시간이 오래소요되는 3개의 delete쿼리를 excutor service를 사용하여 멀티스레드형식으로 1개의 스레드가 1개의 쿼리를 수행하도록 구현해보고 싶습니다. 그런데 멀티스레드를 사용했을때 트랜잭션은 보통 어떻게 처리하시나요.. ? 저는 @transactional 을 선언해서 사용하고 있는데 이는 스레드1개당 트랙잭션이 생성되는거라 제가 의도한데로 롤백이 제대로 안될거라고 하더라구요.. 3개의 쿼리가 모두 성공했을때 커밋되고 그렇지않으면 롤백시키고싶은데 이부분에 대한 지식도 혹시 알수있을까요? 추가로 혹시 해당 질문 관련 강의를 개설해놓으신게 있다면 알려주시면 감사하겠습니다!
synchronized를 unlock에 걸 필요가 없다는건 이해를 했는데 이것 저것 실험(?)을 해보다가 unlock()에 synchronized를 걸면 무한 대기 상태가 지속되는지 이해가 안됩니다..ㅠㅠ제가 계속 고민을 한 로직으로는 Thread-1이 비즈니스 로직을 실행한 후 finally를 실행해서 락을 반납해 Thread-2가 어느 정도 시간이 지난 후에 락을 받아서 실행이 될 것이라고 생각을 했는데 아니라서 많은 고민 끝에 질문을 남겨봅니다..ㅠㅠ 답변 기다리겠습니다..!
public static void main(String[] args) throws InterruptedException, ExecutionException { SumTask task1 = new SumTask(1, 50); SumTask task2 = new SumTask(51, 100); ExecutorService es = Executors.newFixedThreadPool(2); Future<Integer> future1 = es.submit(task1); Future<Integer> future2 = es.submit(task2); log("작업 시작"); long st = System.currentTimeMillis(); Integer sum1 = future1.get(); long end = System.currentTimeMillis(); log(end - st + "ms"); Integer sum2 = future2.get(); log("task1.result = " + sum1); log("task2.result = " + sum2); int sumAll = sum1 + sum2; log("task1 + task2 = " + sumAll); es.close(); } 02:45:32.785 [ main] 작업 시작 02:45:32.785 [pool-1-thread-1] 작업 시작 02:45:32.785 [pool-1-thread-2] 작업 시작 02:45:34.794 [pool-1-thread-1] 작업 완료 result = 1275 02:45:34.794 [pool-1-thread-2] 작업 완료 result = 3775 02:45:34.797 [ main] 2007ms 02:45:34.797 [ main] task1.result = 1275 02:45:34.797 [ main] task2.result = 3775 02:45:34.797 [ main] task1 + task2 = 5050 맨 위 코드를 실행했을 때 위와 같은 출력이 나왔습니다. main 메서드는 BlockingQueue에 등록된 future를 스레드 풀에서 가용 가능한 스레드 만큼 모두 실행 시킨 후에 WAITING 상태로 변경된다고 이해하면 될까요?
안녕하세요 영한님 바로 아래 질문에서 조금 더 의문이 있어 질문드립니다. 4분대 그림에서 c0 소비자 스레드는 데이터를 얻고 notify()해서 스레드 대기 집합에 있는 임의의 스레드를 깨울 것입니다. 만일 이때 소비자 스레드 c1이 깨어나면, 큐에 소비할 데이터가 없어서 다시 스레드 대기 집합으로 들어갈텐데, 그 다음은 notify()를 호출할 스레드가 없어서 모든 스레드가 WAITING 상태로 대기 집합에 있을 것으로 생각합니다. 그러면 이후 다른 새로 생성된 생산자 스레드가 put()을 호출하지 않는한 모든 스레드가 쉬고 있는 상황에 놓이는게 맞을까요? 결국에는 p1을 깨우지 않는 스레드 기아 상태는 이해되는데, 교안에 "최악의 경우 c1 ~ c5 스레드가 반복해서 깨어날 수 있다." 표현에서 스레드들이 계속 연쇄적으로 깨어나는 뉘앙스가 느껴져서 명확히 하고자 여쭤봅니다.
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 교안 "8. 생산자 소비자 문제 1" - 12 page - 3번째 줄 "임계 영역은 synchronized를 영역을 뜻한다." -> "임계 영역은 synchronized를 적용한 영역을 뜻한다." "적용한"이 빠져서 다음 업데이트 때 반영되면 좋을 것 같아 남깁니다. 좋은 강의 항상 감사드립니다 영한님! :)
안녕하세요 영한님! 다중서버로 이루어진 분산환경에서 분산락이 주로 사용되는데 이는 전체 또는 여러 서버에서 동기화가 필요한 데이터여서 그런것이죠? 현재 학습내용인 자바에서 제공하는 락 (서버별로 락을 갖는 방식은) 분산환경에는 적합하지 않고, 서버별로 락을 걸어도 커버 되는 자원에 한정되게 사용되는걸로 이해한게 맞을까요?
안녕하세요. 항상 강의 잘 듣고 있습니다 🙂 public static void main(String[] args) throws InterruptedException { Printer printer = new Printer(); Thread printerThread = new Thread(printer, "printer"); printerThread.start(); Scanner sc = new Scanner(System.in); while (true) { log("프린터할 문서를 입력하세요. 종료 (q): "); String str = sc.nextLine(); if (str.equals("q")) { printerThread.interrupt(); break; } printer.addJob(str); } } static class Printer implements Runnable { Queue<String> jobQueue = new ConcurrentLinkedQueue<>(); @Override public void run() { log("outer 상태 : " + Thread.currentThread().isInterrupted()); while(!Thread.interrupted()) { try { if (jobQueue.isEmpty()) { continue; } String job = jobQueue.poll(); log("출력 시작: " + job + ", 대기 문서: " + jobQueue); log("inner 상태 : " + Thread.currentThread().isInterrupted()); Thread.sleep(3000); log("출력 완료"); } catch (InterruptedException e) { e.printStackTrace(); log("인터럽트!"); System.out.println(e.getMessage()); break; } } log("프린터 종료"); } public void addJob(String str) { jobQueue.offer(str); } } 저는 q를 입력하면 인터럽트 상태가 false로 바뀌게 되고, 프린터 종료 로그가 남을 거라고 생각했습니다. 실행하고 바로 q를 입력하면 제가 예상한 대로 동작하지만, 값을 입력 후 q를 입력하면 Thread.sleep(3000); 이 부분에서 InterruptedException 예외가 발생했습니다. 저는 이 부분에서 의문점이 들었습니다. while(!Thread.interrupted() 1. 인터럽트 상태가 바뀌었을 텐데 왜 예외가 발생하지? 2. 상태가 안 바뀌었나? 라는 생각을 하고 로그를 확인해봤는데 07:21:21.366 [ printer] outer 상태 : false 07:21:21.366 [ main] 프린터할 문서를 입력하세요. 종료 (q): 123 07:21:22.790 [ main] 프린터할 문서를 입력하세요. 종료 (q): 07:21:22.796 [ printer] 출력 시작: 123, 대기 문서: [] 07:21:22.796 [ printer] inner 상태 : false q java.lang.InterruptedException: sleep interrupted at java.base/java.lang.Thread.sleepNanos0(Native Method) at java.base/java.lang.Thread.sleepNanos(Thread.java:491) at java.base/java.lang.Thread.sleep(Thread.java:522) at thread.control.printer.MyPrinterV3$Printer.run(MyPrinterV3.java:46) at java.base/java.lang.Thread.run(Thread.java:1570) 07:21:22.980 [ printer] 인터럽트! sleep interrupted 07:21:22.980 [ printer] 프린터 종료 q를 입력하면 바로 예외가 발생해서 상태가 바뀌었는지는 잘 모르겠습니다. 만약 상태가 안 변했다고 해도 결국 sleep 부분에서 예외가 발생할 텐데, 로그가 안 찍힌 이유도 모르겠습니다. 그래서 여러 번 실행해본 결과 값 입력하고 3초 후 q를 입력하면 예외가 발생하지 않는다는 걸 알게 되었습니다. 잠자고 있는 스레드를 깨워서 문제가 발생하는 것 같은데 제 지식으로는 여기까지인 것 같습니다. 질문 1. while(!Thread.interrupted()) 이 부분에서 인터럽트 상태가 false로 변경되었을 것 같은데 예외가 발생한 이유를 모르겠습니다. 제가 다시 생각해보니 프린터 스레드는 sleep() 때문에 3초 기다리고 있는 상태에서 깨우니 sleep() 부분에서 예외가 발생하고 로그도 안 찍혔을 것 같다는 생각이 들었습니다.
사소한 부분이긴 하지만 오타 제보합니다. synchronized vs ReentrantLock 대기 파트의 ReentrantLock 의 대기2: await() 대기 부분에서 WAITING 상대 로 대기 -> WAITING 상태 로 대기 로 수정이 필요할 것 같습니다. 감사합니다.
자바 고급1 9. 생산자 소비자 문제2 (8~9page) BoundedQueueV5 영상내용과 문서 불일치 합니다. put, take 메소드 내부 문장이 try ~ finally (영상기준) try ~ catch ~finally(문서기준) 영상이 맞는 거 같네요. 검토 바랍니다.
안녕하세요. 김영한님의 강의 잘 보고 있습니다. 바보 같은 질문일 수 있지만, Thread.sleep()과는 다르게 LockSupport.park()는 interrupt()를 이용해서 깨어나도 isInterrupted()가 true인 이유가 궁금합니다. 그냥 단순히 InterruptedException이 발생하지 않기 때문일까요?
그러면 main 메소드 내에 Thread thread1 = new Thread(..); Thread thread2 = new Thread(..); 이걸 실행하면 main 스택프레임내에 참조변수가 저장이될텐데 thread1,thread2가 아닌 this로 저장된다는건가요? 그러면 예를들어, 참조변수 a의 메소드를 실행하게된다면 먼저 스택프레임내에서 참조변수에서 실제 인스턴스가 저장된 힙 주소를 꺼내어서 그 힙주소로 간다음 메소드를 가져오는게 아니라 참조변수 a가 아닌 this 인거죠?
[질문] 2024.08.07 까지는 정액할인, 2024.08.08 부터는 비율할인 정책이 반영되어야 하는 비즈니스 로직이 있고, 이를 스케줄러를 활용하여 2024.08.08 00:00:00에 Setter를 활용하여 비율할인을 구현한 Bean을 Injection 하여 처리하도록 구현했다고 가정하면, 이런 경우에도 아주 아주 엄밀하게 00:00:00에 모든 할인 정책이 완벽히 적용되어야 한다면, 인스턴스 변수에 volatile을 반드시 명시해줘야 하는 것인가요? 경험이 미천하여 웹프로그래밍 할 때 volatile를 사용한 것을 거의 보지 못하였고, 위의 가정처럼 아주 엄밀한 동작을 요구하는 경우는 없었고 그간 별다른 일도 없긴 하였는데, 개념을 듣고 복기해보니 장애의 요인이 될 수 있을 것 같아 여쭙습니다.