C++에서 객체 모니터와 같은 Java를 가장 효율적으로 구현하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1752897

문제

Java에서는 각 개체에 동기화 모니터가 있습니다.그래서 구현은 메모리 사용량 측면에서 꽤 압축되어 있고 빠르기를 바랍니다.

이것을 C++로 포팅할 때 가장 좋은 구현은 무엇입니까?"pthread_mutex_init"보다 더 나은 것이 있어야 한다고 생각합니다. 아니면 Java의 개체 오버헤드가 실제로 그렇게 높은가요?

편집하다:방금 Linux i386의 pthread_mutex_t가 24바이트 크기인지 확인했습니다.각 객체에 대해 이 공간을 예약해야 한다면 그것은 엄청납니다.

도움이 되었습니까?

해결책

태양 핫스팟 JVM이 구현됩니다 얇은 잠금을 사용합니다 비교하고 교체하십시오. 객체가 잠겨 있으면 대기 스레드가 객체를 잠그는 스레드 모니터에서 대기합니다. 이것은 스레드 당 하나의 무거운 잠금 만 있으면됩니다.

다른 팁

어떤 의미에서는 그보다 더 나쁩니다. pthread_mutex_init, 실제로.Java의 대기/통지 때문에 모니터를 구현하려면 쌍을 이루는 뮤텍스와 조건 변수가 필요합니다.

실제로 JVM을 구현할 때 책에 있는 모든 단일 플랫폼별 최적화를 찾아 적용한 다음 몇 가지 새로운 최적화를 고안하여 모니터를 최대한 빠르게 만듭니다.정말 끔찍한 일을 할 수 없다면 가비지 수집을 최적화할 능력이 없는 것입니다 ;-)

한 가지 관찰은 모든 개체가 자체 모니터를 가질 필요는 없다는 것입니다.현재 동기화되지 않은 개체에는 동기화가 필요하지 않습니다.따라서 JVM은 모니터 풀을 생성할 수 있으며 각 객체에는 스레드가 실제로 객체에 대해 동기화하려고 할 때 채워지는 포인터 필드만 있을 수 있습니다(예: 플랫폼별 원자 비교 및 ​​스왑 작업 사용).따라서 모니터 초기화 비용이 객체 생성 비용에 추가될 필요가 없습니다.메모리가 미리 지워졌다고 가정하면 객체 생성은 다음과 같습니다.포인터를 감소시킵니다(gc 등을 실행하는 코드에 대한 예측된 거짓 분기를 사용하여 일종의 경계 검사도 수행함).유형을 채우십시오.가장 많이 파생된 생성자를 호출합니다.제 생각에는 Object 생성자가 아무것도 하지 않도록 설정할 수 있지만 분명히 구현에 따라 많은 것이 달라집니다.

실제로 일반적인 Java 애플리케이션은 동시에 매우 많은 개체를 동기화하지 않으므로 모니터 풀은 잠재적으로 시간과 메모리 측면에서 엄청난 최적화를 제공합니다.

Java가 어떻게 수행하는지 잘 모르겠지만 .NET은 뮤텍스(또는 아날로그 - 이를 보유하는 구조를 "syncblk"라고 함)를 개체에 직접 유지하지 않습니다.오히려 syncblk의 전역 테이블이 있고 개체는 해당 테이블의 인덱스로 해당 syncblk를 참조합니다.게다가 객체는 생성되자마자 syncblk를 얻지 못합니다. 대신 첫 번째 잠금 시 요청 시 생성됩니다.

나는 스레드로부터 안전한 방식으로 개체와 해당 syncblk를 연결하기 위해 원자 비교 및 ​​교환을 사용한다고 가정합니다(실제로 어떻게 수행되는지는 모릅니다!).

  1. 숨겨진 것을 확인하세요 syncblk_index 0에 대한 객체의 필드입니다.0이 아니면 잠그고 진행하고, 아니면...
  2. 전역 테이블에 새 syncblk를 만들고 이에 대한 인덱스를 가져옵니다(전역 잠금은 필요에 따라 여기에서 획득/해제됩니다).
  3. 비교하고 교환하여 객체 자체에 기록합니다.
  4. 이전 값이 0인 경우(0은 유효한 인덱스가 아니며 숨겨진 인덱스의 초기 값이라고 가정) syncblk_index 필드), syncblk 생성에 대한 이의가 제기되지 않았습니다.그것을 잠그고 진행하십시오.
  5. 이전 값이 0이 아니면 다른 사람이 이미 syncblk를 생성하여 우리가 생성하는 동안 객체와 연결한 것이므로 이제 해당 syncblk의 인덱스를 갖게 됩니다.방금 만든 것을 폐기하고 얻은 것을 잠급니다.

따라서 개체당 오버헤드는 최상의 경우 4바이트(syncblk 테이블에 대한 32비트 인덱스 가정)이지만 실제로 잠긴 개체의 경우 더 큽니다.개체를 거의 잠그지 않는 경우 이 체계는 리소스 사용량을 줄이는 좋은 방법처럼 보입니다.그러나 결국 대부분 또는 모든 객체를 잠가야 하는 경우 객체 내에 직접 뮤텍스를 저장하는 것이 더 빠를 수 있습니다.

확실히 당신은 그러한 모니터가 필요하지 않습니다 모든 물체!

Java에서 C ++로 포팅 할 때, 모든 것을 맹목적으로 복사하는 것이 나쁜 생각으로 저를 놀라게합니다. Java에 가장 적합한 구조는 C ++에 가장 적합하지 않습니다. Java에는 쓰레기 수집이 있고 C ++가 그렇지 않기 때문에 적어도.

실제로 필요한 객체에만 모니터를 추가하십시오. 유형의 일부 인스턴스만이 동기화가 필요한 경우 동기화에 필요한 뮤트 (및 조건 변수)가 포함 된 래퍼 클래스를 작성하는 것은 어렵지 않습니다. 다른 사람들이 이미 말했듯이, 대안은 객체 주소의 해시를 사용하여 배열을 인덱싱하는 등 각 객체마다 하나를 선택하는 수단을 가진 동기화 객체의 풀을 사용하는 것입니다.

각 턴마다 플랫폼 세부 사항에 의존하지 않고 Roost Thread Library 또는 새로운 C ++ 0X 표준 스레드 라이브러리를 사용하여 휴대 성을 사용합니다. 부스트. 스레드 Linux, MacOSX, Win32, Solaris, HP-UX 등을 지원합니다. 나의 C ++ 0X 스레드 라이브러리 구현 현재 Windows 및 Linux 만 지원하지만 다른 구현은 적절한 과정에서 사용할 수있게됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top