비유하자면, 사물은 큰 집과 같아서 문은 항상 열려 있습니다. 집에는 많은 방(메서드라고도 함)이 있습니다. 이러한 룸은 잠겨 있거나(동기화 방법) 잠금 해제되어 있습니다(일반 방법). 방 문에 열쇠가 있습니다. 이 열쇠로 잠긴 모든 방을 열 수 있습니다. 또한 이 객체의 메소드를 호출하려는 모든 스레드를 이 집의 특정 방에 들어가려는 사람들과 비교합니다. 이것이 전부입니다. 이러한 것들이 서로 어떻게 작동하는지 살펴보겠습니다.
여기서는 먼저 전제 조건을 명확히 합니다. 객체에는 하나 이상의 동기화된 메서드가 있습니다. 그렇지 않으면 이 키는 의미가 없습니다. 물론 우리의 그런 주제는 없을 것입니다.
어떤 사람이 잠긴 방에 들어가고 싶어합니다. 그는 집 문으로 와서 거기에 열쇠가 있는 것을 봅니다(아직 잠긴 방을 사용하고 싶어하는 사람이 없음을 나타냄). 그래서 그는 올라가서 열쇠를 받고 계획한 대로 방을 사용했습니다. 그는 잠긴 방을 사용할 때마다 즉시 열쇠를 반환한다는 점에 유의하십시오. 두 개의 잠긴 방을 연속으로 사용하고 싶어도 열쇠를 반납하고 그 사이에 다시 가져와야 합니다.
따라서 일반적인 상황에서 열쇠를 사용하는 원칙은 '사용할 때 빌려주고, 사용하자마자 반납한다'는 것이다.
이때, 잠금 해제된 객실은 다른 사람이 제한 없이 사용할 수 있습니다. 1인이 1개의 객실을 사용할 수도 있고, 2명이 1개의 객실을 사용할 수도 있습니다. 그러나 누군가 잠긴 방에 들어가고 싶다면 문으로 달려가서 살펴보아야 합니다. 열쇠가 있으면 당연히 가지고 나가면 됩니다. 열쇠가 없으면 기다리기만 하면 됩니다.
많은 사람이 열쇠를 기다리고 있는데, 열쇠가 반납되면 누가 먼저 열쇠를 받게 될까요? 보장되지 않습니다. 앞의 예에서 잠긴 방 두 개를 연속으로 사용하려는 사람처럼, 열쇠를 반납할 때 다른 사람이 열쇠를 기다리고 있다면 이 사람이 다시 열쇠를 얻을 수 있다는 보장은 없습니다. (JAVA 사양에는 Thread.sleep()이 휴식 후 실행으로 돌아가는 데 걸리는 시간, 우선 순위가 같은 스레드가 먼저 실행될 때와 같은 보장이 없다는 것이 여러 곳에서 명시되어 있습니다. 객체에 액세스하기 위한 잠금이 해제되고 대기 풀의 여러 스레드가 어떤 스레드의 우선순위를 갖게 될지 등이 결정됩니다. 최종 결정은 JVM에 있다고 생각합니다. 보장이 없는 이유는 JVM이 위의 결정을 내릴 때입니다. 단순히 조건에 따라 판단하는 것이 아니라, 판단 조건이 너무 많으면 JAVA의 추진에 영향을 미칠 수도 있지만, 지적재산권 보호의 이유 때문일 수도 있다고 생각합니다. 컴퓨터 자체가 지시에 따라 작동하기 때문에 불합리한 것이 아니라 결정된 것입니다. 임의적인 것처럼 보이더라도 실제로는 컴퓨터를 연구한 사람이라면 누구나 찾을 수 있는 규칙이 있습니다. 컴퓨터는 의사 난수(pseudo-random)입니다. 숫자는 사람들이 특정한 방법을 사용하여 작성한 것이며, 또한 결정하기가 너무 번거롭고 의미가 없기 때문에 확실하지 않은 경우도 있습니다. .)
동기화된 코드 블록을 다시 살펴보겠습니다. 동기화 방식과는 약간 다릅니다.
1. 크기 측면에서 동기화 코드 블록은 동기화 방법보다 작습니다. 동기화된 코드 블록은 잠긴 화면으로 분리된 잠금 해제된 방의 공간으로 생각할 수 있습니다.
2. 동기화 코드 블록은 다른 객체의 키를 수동으로 지정할 수도 있습니다. 이 화면의 자물쇠를 여는 데 사용할 수 있는 열쇠를 지정하는 것과 같습니다. 이 집의 열쇠를 사용하여 열 수 있으며, 이 경우 다른 집으로 달려가야 합니다. 그 열쇠를 얻고 그 집 열쇠를 사용하여 이 집의 잠긴 화면을 엽니다.
당신이 획득한 다른 집의 열쇠는 다른 사람이 그 집의 잠금 해제된 방에 들어가는 것을 막지 못한다는 것을 기억하십시오.
동기화된 코드 블록을 사용하는 이유는 무엇입니까? 내 생각에는 다음과 같아야 한다고 생각합니다. 우선 프로그램의 동기화 부분이 작업 효율성에 영향을 미치며 메서드는 일반적으로 일부 지역 변수를 먼저 생성한 다음 이러한 변수에 대해 계산, 표시 등과 같은 일부 작업을 수행합니다. ; 및 동기화 적용 코드가 많을수록 효율성에 미치는 영향은 더욱 심각해집니다. 그래서 우리는 일반적으로 영향 범위를 가능한 한 작게 유지하려고 노력합니다. 어떻게 하나요? 동기화된 코드 블록. 작업과 같이 동기화되어야 하는 메서드 부분만 동기화합니다.
또한, 동기화 코드 블록에서는 키를 지정할 수 있습니다. 이 기능은 일정 시간 내에 객체의 키를 점유할 수 있다는 추가적인 이점을 제공합니다. 정상적인 상황에서 키를 사용하는 원칙에 대해 이전에 말한 것을 기억하십시오. 이는 일반적인 상황이 아닙니다. 획득한 키는 영원히 반환되지 않으며 동기화된 코드 블록을 종료할 때만 반환됩니다.
두 개의 잠긴 방을 연속으로 사용하고 싶어했던 앞서의 사람의 비유를 사용해 보겠습니다. 한 객실 이용 후 다른 객실을 계속 이용하려면 어떻게 해야 하나요? 동기화된 코드 블록을 사용합니다. 먼저 다른 스레드를 만들고 동기화 코드 블록을 만든 다음 해당 코드 블록의 잠금 장치가 집 열쇠를 가리키도록 합니다. 그런 다음 해당 스레드를 시작하십시오. 해당 코드 블록에 들어갈 때 집 열쇠를 얻을 수 있는 한 해당 코드 블록을 나갈 때까지 보관할 수 있습니다. 즉, 이 방의 잠긴 방을 모두 탐색할 수도 있고 심지어 잠을 잘 수도 있지만(10*60*1000) 여전히 문 앞에는 1000개의 스레드가 열쇠를 기다리고 있습니다. 꽤 즐겁습니다.
sleep() 메소드와 키 사이의 상관관계에 대해 이야기해 보겠습니다. 키를 가져온 후 스레드가 강제로 sleep() 상태가 되고 동기화 콘텐츠가 완료되지 않은 경우 키는 여전히 그대로 유지됩니다. 키는 다시 실행되어 모든 동기화 콘텐츠가 완료될 때까지 반환되지 않습니다. 그 사람은 일을 하다가 피곤해서 쉬러 갔다는 걸 기억하세요. 그는 하고 싶은 일을 끝내지 못했습니다. 다른 사람이 방에 들어와 내부를 어지럽히는 것을 막기 위해 잠잘 때도 몸에 유일한 열쇠를 차고 있어야 했다.
마지막으로, 누군가는 왜 각 문에 하나의 열쇠가 필요한 대신 각 문을 여는 데 하나의 열쇠가 필요한지 물을 수 있습니다. 나는 이것이 순전히 복잡성의 문제라고 생각합니다. 하나의 문에 하나의 열쇠가 있는 것이 확실히 더 안전하지만 많은 문제를 수반하게 됩니다. 키의 생성, 보관, 획득, 반환 등 동기화 방법의 수가 증가함에 따라 복잡성이 기하학적으로 증가하여 효율성에 심각한 영향을 미칠 수 있습니다. 이는 트레이드오프(trade-off)의 문제라고 볼 수 있다. 보안을 조금 높이기 위해 효율성을 크게 줄이는 것은 얼마나 바람직하지 않은 일입니까?