자바 synchronized(this)와 synchronized(object)의 차이
25576 단어 Javasynchronized
최근 글 라 이 드 4.11 의 소스 코드 를 보다 가 본의 아니 게 다음 코드 를 봤 다.왜 이 걸 직접 쓰 지 않 으 면 되 는 지 궁금 하 네요.굳이 Object 대상 을 쓰 겠 다 고?뒤에 한 차례 의 탐 구 를 통 해 차이 점 을 발견 하 였 다.
public static class SynchronizedPool<T> extends SimplePool<T> {
private final Object mLock = new Object();
public SynchronizedPool(int maxPoolSize) {
super(maxPoolSize);
}
@Override
public T acquire() {
synchronized (mLock) {
return super.acquire();
}
}
@Override
public boolean release(@NonNull T element) {
synchronized (mLock) {
return super.release(element);
}
}
}
1.동기 화 작용 이 같다.다 중 스 레 드 가 같은 인 스 턴 스 방법 에 대한 동기 화 를 실현 할 수 있 습 니 다.
둘째,자물쇠 대상 이 다르다.synchronized(this),잠 긴 대상 은 this,클래스 의 인 스 턴 스 입 니 다.synchronized(object),잠 긴 대상 은 object 입 니 다.
class Test{
private final Object object = new Object();
public void print(){
synchronized (object){
System.out.println("xxxx");
}
}
}
class Test{
public void print(){
synchronized (this){
System.out.println("xxxx");
}
}
}
3.그런데 왜 synchronized(object)라 는 방식 으로 object 대상 을 하나 더 만 들 었 습 니까?다음 코드 부터 봅 시다.
class STest{
public void print(){
synchronized (this){
System.out.println("xxxx");
}
}
}
public class SynchronizeMain {
public static void main(String[] args) throws InterruptedException {
STest sTest = new STest();
// Thread 1
Thread t1 = new Thread(() -> {
sTest.print();
});
// Thread 2
Thread t2 = new Thread(() -> {
try {
synchronized (sTest){
while (true);
}
} catch (Exception e) {
System.out.println("Exception="+e.getMessage());
}
});
t2.start();
t1.start();
}
}
출력 결 과 는 아무것도 없습니다!이 유 는 synchronized(this)의 잠 금 대상 이 this 이기 때 문 입 니 다.만약 에 이런 방식 을 사용 하면 잠 금 대상(인 스 턴 스)을 다른 사람 이 가 져 오 면 다른 사람 이 스 레 드 2 처럼 스 레 드 를 열 면 당신 의 Thread 1,이 정상 적 인 작업 스 레 드 는 영원히 실행 되 지 못 하고 잠 금 을 만 듭 니 다.다른 예 를 다시 봅 시다.
class STest{
private final Object object = new Object();
public void print(){
synchronized (object){
System.out.println("xxxx");
}
}
}
public class SynchronizeMain {
public static void main(String[] args) throws InterruptedException {
STest sTest = new STest();
// Thread 1
Thread t1 = new Thread(() -> {
sTest.print();
});
// Thread 2
Thread t2 = new Thread(() -> {
try {
synchronized (sTest){
while (true);
}
} catch (Exception e) {
System.out.println("Exception="+e.getMessage());
}
});
t2.start();
Thread.sleep(1000);
t1.start();
}
}
출력 결 과 는 xxxx!synchronized(object),잠 긴 대상 이 object 이기 때문이다.그래서 sTest 의 인 스 턴 스 를 받 았 고 Thread 1 의 정상 적 인 실행 에 영향 을 주지 않 습 니 다.
4.만약 에 제 가 반 사 를 통 해 object 변 수 를 가 져 와 Thread 2 에 들 어가 면 어떻게 될까요?
그렇다면 Thread 1,이 정상 적 인 작업 스 레 드 는 영원히 실행 되 지 않 고 잠 금 을 만 들 수 있 습 니 다.Talk is cheap, Show me code:
class STest{
private final Object object = new Object();
public void print(){
synchronized (object){
System.out.println("xxxx");
}
}
}
public class SynchronizeMain {
public static void main(String[] args) throws InterruptedException {
STest sTest = new STest();
// Thread 1
Thread t1 = new Thread(() -> {
sTest.print();
});
// Thread 2
Thread t2 = new Thread(() -> {
try {
synchronized (getPrivateField(sTest,"object")){
while (true);
}
} catch (Exception e) {
System.out.println("Exception="+e.getMessage());
}
});
t2.start();
Thread.sleep(1000);
t1.start();
}
public static Object getPrivateField(Object instance, String filedName) throws NoSuchFieldException, IllegalAccessException {
Field field = instance.getClass().getDeclaredField(filedName);
field.setAccessible(true);
return field.get(instance);
}
}
출력 결 과 는 아무것도 없습니다!synchronized(object)의 잠 금 대상 은 object 이 고 object 는 Thread 2 에 의 해 점용 되 었 기 때 문 입 니 다.
총결산
잠 금 대상 을 선택 할 때 잠 금 대상 의 안전성 을 고려 하여 잠 금 대상 이 노출 되 지 않도록 해 야 한다.많은 소스 라 이브 러 리 에서 사용 하 는 동기 화 방법 블록 은 object 설정 을 통 해 이 루어 집 니 다.비록 그것 은 여전히 반 사 를 통 해 풀 수 있 지만.그러나 보장 과 인위적인 오 작 동 으로 인 한 자물쇠 가 있 을 수 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.