Nice programing

동기화 된 블록이 동기화 된 방법보다 나은 이유는 무엇입니까?

nicepro 2021. 1. 9. 11:40
반응형

동기화 된 블록이 동기화 된 방법보다 나은 이유는 무엇입니까?


스레딩에서 동기화를 배우기 시작했습니다.

동기화 된 방법 :

public class Counter{

  private static int count = 0;

  public static synchronized int getCount(){
    return count;
  }

  public synchronized setCount(int count){
     this.count = count;
  }

}

동기화 된 블록 :

public class Singleton{

private static volatile Singleton _instance;

public static Singleton getInstance(){
   if(_instance == null){
            synchronized(Singleton.class){
              if(_instance == null)
              _instance = new Singleton();
            }
   }
   return _instance;
}

동기화 방법과 동기화 블록은 언제 사용해야합니까? 동기화 된 블록이 동기화 된 방법보다 나은 이유는 무엇입니까?


더 나은 문제가 아니라 단지 다릅니다.

메서드를 동기화하면 개체 자체와 효과적으로 동기화됩니다. 정적 메서드의 경우 개체의 클래스와 동기화됩니다. 따라서 다음 두 코드는 동일한 방식으로 실행됩니다.

public synchronized int getCount() {
    // ...
}

이것은 당신이 이것을 쓴 것과 같습니다.

public int getCount() {
    synchronized (this) {
        // ...
    }
}

특정 개체에 대한 동기화를 제어하거나 메서드의 일부만 개체에 동기화하려는 경우 synchronized블록 을 지정합니다 . synchronized메서드 선언에 키워드 를 사용하면 전체 메서드가 개체 또는 클래스에 동기화됩니다.


일반적으로 문제가되지는 않지만 보안 관점에서 메서드에 넣는 것보다 개인 개체에 동기화를 사용하는 것이 좋습니다.

메서드에 넣는 것은 스레드 안전성을 제공하기 위해 객체 자체의 잠금을 사용하고 있음을 의미합니다. 이러한 종류의 메커니즘을 사용하면 코드의 악의적 인 사용자가 개체에 대한 잠금을 획득하고 영구적으로 유지하여 다른 스레드를 효과적으로 차단할 수 있습니다. 악의가없는 사용자는 실수로 동일한 작업을 효과적으로 수행 할 수 있습니다.

개인 데이터 멤버의 잠금을 사용하면 악의적 인 사용자가 개인 개체에 대한 잠금을 얻을 수 없기 때문에이를 방지 할 수 있습니다.

private final Object lockObject = new Object();

public void getCount() {
    synchronized( lockObject ) {
        ...
    }
}

이 기술은 Bloch의 Effective Java (2nd Ed), 항목 # 70에 언급되어 있습니다.


차이점은 잠금을 획득하는 것입니다.

  • 동기화 된 메서드는 전체 개체에 대한 잠금을 획득합니다. 즉, 하나의 스레드에서 메서드를 실행하는 동안 다른 스레드는 전체 개체에서 동기화 된 메서드를 사용할 수 없습니다.

  • 동기화 된 블록은 동기화 된 키워드 뒤의 괄호 사이에있는 개체의 잠금을 획득합니다. 동기화 된 블록이 종료 될 때까지 다른 스레드는 잠긴 개체에 대한 잠금을 획득 할 수 없습니다.

따라서 전체 개체를 잠 그려면 동기화 된 방법을 사용하십시오. 객체의 다른 부분을 다른 스레드에서 액세스 할 수 있도록하려면 동기화 된 블록을 사용하십시오.

If you choose the locked object carefully, synchronized blocks will lead to less contention, because the whole object/class is not blocked.

This applies similarly to static methods: a synchronized static method will acquire a lock in the whole class object, while a synchronized block inside a static method will acquire a lock in the object between parentheses.


Define 'better'. A synchronized block is only better because it allows you to:

  1. Synchronize on a different object
  2. Limit the scope of synchronization

Now your specific example is an example of the double-checked locking pattern which is suspect (in older Java versions it was broken, and it is easy to do it wrong).

If your initialization is cheap, it might be better to initialize immediately with a final field, and not on the first request, it would also remove the need for synchronization.


Difference between synchronized block and synchronized method are following:

  1. synchronized block reduce scope of lock, but synchronized method's scope of lock is whole method.
  2. synchronized block has better performance as only the critical section is locked but synchronized method has poor performance than block.
  3. synchronized block provide granular control over lock but synchronized method lock either on current object represented by this or class level lock.
  4. synchronized block can throw NullPointerException but synchronized method doesn't throw.
  5. synchronized block: synchronized(this){}

    synchronized method: public synchronized void fun(){}


synchronized should only be used when you want your class to be Thread safe. In fact most of the classes should not use synchronized anyways. synchronized method would only provide a lock on this object and only for the duration of its execution. if you really wanna to make your classes thread safe, you should consider making your variables volatile or synchronize the access.

one of the issues of using synchronized method is that all of the members of the class would use the same lock which will make your program slower. In your case synchronized method and block would execute no different. what I'd would recommend is to use a dedicated lock and use a synchronized block something like this.

public class AClass {
private int x;
private final Object lock = new Object();     //it must be final!

 public void setX() {
    synchronized(lock) {
        x++;
    }
 }
}

In your case both are equivalent!

Synchronizing a static method is equivalent to a synchronized block on corresponding Class object.

In fact when you declare a synchronized static method lock is obtained on the monitor corresponding to the Class object.

public static synchronized int getCount() {
    // ...
}

is same as

public int getCount() {
    synchronized (ClassName.class) {
        // ...
    }
}

Because lock is expensive, when you are using synchronized block you lock only if _instance == null, and after _instance finally initialized you'll never lock. But when you synchronize on method you lock unconditionally, even after the _instance is initialized. This is the idea behind double-checked locking optimization pattern http://en.wikipedia.org/wiki/Double-checked_locking.


It should not be considered as a question of best for usage, but it really depends on the use case or the scenario.

Synchronized Methods

An entire method can be marked as synchronized resulting an implicit lock on the this reference (instance methods) or class (static methods). This is very convenient mechanism to achieve synchronization.

Steps A thread access the synchronized method. It implicitly acquires the lock and execute the code. If other thread want to access the above method, it has to wait. The thread can't get the lock, will be blocked and has to wait till the lock is released.

Synchronized Blocks

To acquire a lock on an object for a specific set of code block, synchronized blocks are the best fit. As a block is sufficient, using a synchronized method will be a waste.

More specifically with Synchronized Block , it is possible to define the object reference on which are want to acquire a lock.

ReferenceURL : https://stackoverflow.com/questions/20906548/why-is-synchronized-block-better-than-synchronized-method

반응형