묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
yield()를 추가해도 무한반복은 계속해서 발생하지 않을까요?
안녕하세요. 강의 수강 중 궁금한 것이 있어 질문드립니다.MyPrinterV4에서 yield()를 추가해도 인터럽트 되지 않은 상태에서 while문에서 무한 반복이 발생(성능저하의 근본 원인)하는 것은 V3와 동일하기 때문에 때문에 성능 향상이 있을까 싶습니다.
-
미해결김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
trylock(1500)질문입니다
안녕하세요 강의 잘보고 있습니다. 강의 내용중 tryLock메서드 실습 부분에 서 tryLock에 인자로 500 밀리초를 넘겨 0.5초동안 락을 획득하지못하면 포기하는 것을 실습했습니다. 추가로 1500밀리초를 넘겨서 돌려봤는데 이때도 락을 얻지 못했습니다. 출금시간은 1초라서 락해제까지 완료가 된상태인데 왜 다음스레드가 락을 얻지 못할까여,, ㅠㅠ19:00:56.252 [ Thread-1] 거래 시작: BankAccountV519:00:56.252 [ Thread-0] 거래 시작: BankAccountV519:00:56.254 [ Thread-1] [검증 시작] 출금액: 800, 잔액: 100019:00:56.254 [ Thread-1] [검증 완료] 출금액: 800, 잔액: 100019:00:56.752 [ main] t1 state: TIMED_WAITING19:00:56.752 [ main] t2 state: TIMED_WAITING19:00:57.258 [ Thread-1] [출금 완료] 출금액: 800, 잔액: 20019:00:57.258 [ Thread-1] Thread-1 락 해제19:00:57.258 [ Thread-1] 거래 종료19:00:57.758 [ Thread-0] [진입 실패] 이미 처리중인 작업이 있습니다 if (!lock.tryLock(1500, TimeUnit.MILLISECONDS)) { log("[진입 실패] 이미 처리중인 작업이 있습니다") return false } lock.lock() //그냐 트라이랑 세트라 보삼 try { log("[검증 시작] 출금액: $amount, 잔액: $balance") if (amount > balance) { log("[검증 실패] 출금액: $amount, 잔액: $balance") return false } log("[검증 완료] 출금액: $amount, 잔액: $balance") Thread.sleep(1000) balance -= amount log("[출금 완료] 출금액: $amount, 잔액: $balance") } finally { log("${Thread.currentThread().name} 락 해제") lock.unlock() //언락 반드시 해야함 }코드가 코틀린인점 죄송합니다.. 자바랑 같은라이브러리를 사용해서 혹시나해서 여쭤봅니다
-
해결됨김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
비공정 모드가 공정 모드가 빠른 이유
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문 전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]비공정 모드가 공정 모드가 빠른 이유가 뭔지 자세히 궁금합니다. 비공정 모드에서도 어느 정도 대기큐가 있다고 하셨는데 그 걸 제외하고 공정 모드에서는 대기큐를 사용하면 어떤 스레드가 다음 락을 가져야할 지 알기 때문에 좀 더 빠르지 않나? 라는 생각이 들어서요.. 그리고 비공정 모드에서는 반대로 대기큐를 사용하지 않았기 때문에 공정 모드보다 락 얻기 위한 경합이 일어나서 좀 더 느릴 수 있는거 아닌가..? 싶어서 여쭤봅니다..시스템 상황에서 어떻게 비공정 모드가 공정 모드보다 빠른지 이해가 가지 않네요..ㅠㅠ
-
미해결김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
실무에서 excutor service사용
안녕하세요. 실무에서 시간이 오래소요되는 3개의 delete쿼리를 excutor service를 사용하여 멀티스레드형식으로 1개의 스레드가 1개의 쿼리를 수행하도록 구현해보고 싶습니다. 그런데 멀티스레드를 사용했을때 트랜잭션은 보통 어떻게 처리하시나요.. ? 저는 @transactional 을 선언해서 사용하고 있는데 이는 스레드1개당 트랙잭션이 생성되는거라 제가 의도한데로 롤백이 제대로 안될거라고 하더라구요.. 3개의 쿼리가 모두 성공했을때 커밋되고 그렇지않으면 롤백시키고싶은데 이부분에 대한 지식도 혹시 알수있을까요? 추가로 혹시 해당 질문 관련 강의를 개설해놓으신게 있다면 알려주시면 감사하겠습니다!
-
해결됨김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
unlock()에 synchronized를 걸면 왜 무한루프를 도는지가 이해가 안됩니다..ㅠㅠ
synchronized를 unlock에 걸 필요가 없다는건 이해를 했는데 이것 저것 실험(?)을 해보다가 unlock()에 synchronized를 걸면 무한 대기 상태가 지속되는지 이해가 안됩니다..ㅠㅠ제가 계속 고민을 한 로직으로는 Thread-1이 비즈니스 로직을 실행한 후 finally를 실행해서 락을 반납해 Thread-2가 어느 정도 시간이 지난 후에 락을 받아서 실행이 될 것이라고 생각을 했는데 아니라서 많은 고민 끝에 질문을 남겨봅니다..ㅠㅠ 답변 기다리겠습니다..!
-
미해결김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
future.get()
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 상태로 변경된다고 이해하면 될까요?
-
미해결김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
스레드 기아상태 - 모든 스레드가 wait인 상황
안녕하세요 영한님바로 아래 질문에서 조금 더 의문이 있어 질문드립니다.4분대 그림에서 c0 소비자 스레드는 데이터를 얻고 notify()해서 스레드 대기 집합에 있는 임의의 스레드를 깨울 것입니다.만일 이때 소비자 스레드 c1이 깨어나면, 큐에 소비할 데이터가 없어서 다시 스레드 대기 집합으로 들어갈텐데, 그 다음은 notify()를 호출할 스레드가 없어서 모든 스레드가 WAITING 상태로 대기 집합에 있을 것으로 생각합니다. 그러면 이후 다른 새로 생성된 생산자 스레드가 put()을 호출하지 않는한 모든 스레드가 쉬고 있는 상황에 놓이는게 맞을까요? 결국에는 p1을 깨우지 않는 스레드 기아 상태는 이해되는데,교안에 "최악의 경우 c1 ~ c5 스레드가 반복해서 깨어날 수 있다." 표현에서 스레드들이 계속 연쇄적으로 깨어나는 뉘앙스가 느껴져서 명확히 하고자 여쭤봅니다.
-
미해결김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
오타 제보드려요!
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]교안 "8. 생산자 소비자 문제 1" - 12 page - 3번째 줄"임계 영역은 synchronized를 영역을 뜻한다."-> "임계 영역은 synchronized를 적용한 영역을 뜻한다.""적용한"이 빠져서 다음 업데이트 때 반영되면 좋을 것 같아 남깁니다.좋은 강의 항상 감사드립니다 영한님! :)
-
미해결김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
분산락과 서버별 락에 대해 질문드립니다!
안녕하세요 영한님!다중서버로 이루어진 분산환경에서 분산락이 주로 사용되는데 이는 전체 또는 여러 서버에서 동기화가 필요한 데이터여서 그런것이죠? 현재 학습내용인 자바에서 제공하는 락 (서버별로 락을 갖는 방식은) 분산환경에는 적합하지 않고,서버별로 락을 걸어도 커버 되는 자원에 한정되게 사용되는걸로 이해한게 맞을까요?
-
미해결김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
프록시 패턴 vs 데코레이터 패턴
섹션11에서 프록시에 대한 설명이 있는데요, 제가 알고 있는 데코레이터 패턴과 완전히 동일한 거 같은데 둘간의 차이점은 뭐라고 봐야하나요?
-
미해결김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
q를 입력하면 예외가 발생하는데 그 이유를 모르겠습니다.
안녕하세요. 항상 강의 잘 듣고 있습니다 🙂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() 부분에서 예외가 발생하고 로그도 안 찍혔을 것 같다는 생각이 들었습니다.
-
미해결김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
오타 제보합니다
사소한 부분이긴 하지만 오타 제보합니다.synchronized vs ReentrantLock 대기 파트의 ReentrantLock 의 대기2: await() 대기 부분에서 WAITING 상대로 대기 -> WAITING 상태로 대기로 수정이 필요할 것 같습니다.감사합니다.
-
미해결김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
모든 스레드가 wait 상태
강의 4분대 그림에서 c0가 queue 가 비어서 wait 상태로 들어가면 notify를 호출하지 않기때문에 모든 스레드가 wait 상태에 들어가지 않나요? while문을 벗어나야 notify를 호출할 수 있잖아요. 어떻게 되는지 궁금합니다.
-
해결됨김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
[생산자 소비자 문제2] Lock(ReentrantLcok) 강의 화면의 이미지와 강의 자료가 다르게 나와 있습니다.
강의에서는, ReentrantLock 의 대기 큐까지 포함된 이미지로 설명을 하시는데, 강의 자료에서는, 대기 큐가 빠진 상태로 나와 있습니다. [강의 화면] [강의 자료]S
-
미해결김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
오타
자바 고급19. 생산자 소비자 문제2 (8~9page)BoundedQueueV5 영상내용과 문서 불일치 합니다.put, take 메소드 내부 문장이try ~ finally (영상기준)try ~ catch ~finally(문서기준)영상이 맞는 거 같네요.검토 바랍니다.
-
해결됨김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
getter메소드에 락관리
3:05에서 getBalance()에서 계속 동시성 관리를 하는 이유가 메모리가시화 문제 때문인가요? 만약 그런거라면 앞으로 멀티스레드환경에 노출된 인스턴스변수들은 단순 반환만하는 getter메소드에서도 무조건 volitile이나 락관리를 해야되는게 맞을까요?
-
미해결김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
LockSupport.park()의 isInterrupted() 질문
안녕하세요. 김영한님의 강의 잘 보고 있습니다.바보 같은 질문일 수 있지만, Thread.sleep()과는 다르게 LockSupport.park()는 interrupt()를 이용해서 깨어나도 isInterrupted()가 true인 이유가 궁금합니다.그냥 단순히 InterruptedException이 발생하지 않기 때문일까요?
-
해결됨김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
this 질문
그러면 main 메소드 내에Thread thread1 = new Thread(..);Thread thread2 = new Thread(..); 이걸 실행하면main 스택프레임내에 참조변수가 저장이될텐데thread1,thread2가 아닌 this로 저장된다는건가요? 그러면 예를들어, 참조변수 a의 메소드를 실행하게된다면 먼저 스택프레임내에서 참조변수에서 실제 인스턴스가 저장된 힙 주소를 꺼내어서 그 힙주소로 간다음 메소드를 가져오는게 아니라 참조변수 a가 아닌 this 인거죠?
-
해결됨김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
스레드와 메모리영역 질문
1:31 경에 쓰레드1,2,3 3개의 객체를 만들고 실행하잖아요 그러면 1:49 그림에서 3개의 인스턴스가 그려져야하는거 아닌가요?반복문을 통해 Thread를 100개 실행하고 있습니다. 여기서, thread 참조변수에 Thread 객체를 생성하고 있던데, 그렇다면 for문 순회하나하고 블록 종료시점에 스택프레임이 제거되어 thread 참조변수는 제거될것이고 힙영역에 Thread 객체가 존재하다가 나중에 GC 실행시점에 Thread 객체가 지워질것으로 보이는데 맞나요? 만약 그렇게 Thread 객체가 지워진다면 실행중이던 스레드도 중단되나요?
-
해결됨김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
메서드 영역에 static 변수?
자바 8부터 Heap 영역에 Static Object(Static Variable, static객체 , static method)이 존재하고MetaSpace에는 static reference만 저장한다고 아래 글에서 읽었습니다.https://openjdk.org/jeps/122어떤게 맞는건가요? 제가 오역한거같지는 않은게 다른 분들도 그렇게 말씀하시는것 같습니다.https://jgrammer.tistory.com/entry/JAVA-Java8%EB%B6%80%ED%84%B0%EB%8A%94-static%EC%9D%B4-heap%EC%98%81%EC%97%AD%EC%97%90-%EC%A0%80%EC%9E%A5%EB%90%9C%EB%8B%A4