예를 들어 동기화 된 블록보다 동기화 된 방법의 장점을 알려주는 사람이 있습니까?
답변
누구든지 예를 들어 동기화 된 블록보다 동기화 된 방법의 장점을 말해 줄 수 있습니까? 감사.
블록보다 동기화 된 방법을 사용하면 확실한 이점이 없습니다.
아마도 유일한 것은 (그러나 나는 그것을 이점이라고 부르지 않을 것입니다) 당신은 객체 참조를 포함 할 필요가 없다는 것 this
입니다.
방법:
public synchronized void method() { // blocks "this" from here....
...
...
...
} // to here
블록:
public void method() {
synchronized( this ) { // blocks "this" from here ....
....
....
....
} // to here...
}
보다? 전혀 이점이 없습니다.
블록 은 다른 객체를 잠금으로 사용할 수 있지만 메서드를 동기화하면 전체 객체가 잠길 수 있기 때문에 대부분의 유연성에서 블록 이 메서드보다 장점이 있습니다.
비교:
// locks the whole object
...
private synchronized void someInputRelatedWork() {
...
}
private synchronized void someOutputRelatedWork() {
...
}
vs.
// Using specific locks
Object inputLock = new Object();
Object outputLock = new Object();
private void someInputRelatedWork() {
synchronized(inputLock) {
...
}
}
private void someOutputRelatedWork() {
synchronized(outputLock) {
...
}
}
또한 방법이 커지면 동기화 된 섹션을 계속 분리 할 수 있습니다.
private void method() {
... code here
... code here
... code here
synchronized( lock ) {
... very few lines of code here
}
... code here
... code here
... code here
... code here
}
답변
유일한 차이점은 동기화 된 블록이 동기화 할 객체를 선택할 수 있다는 것입니다. 동기화 된 메소드는 'this'
(또는 동기화 된 클래스 메소드의 해당 클래스 인스턴스) 만 사용할 수 있습니다 . 예를 들어 다음은 의미 상 동일합니다.
synchronized void foo() {
...
}
void foo() {
synchronized (this) {
...
}
}
후자는 모든 객체, 종종 멤버 변수 의 관련 잠금을 위해 경쟁 할 수 있기 때문에 더 유연 합니다. 또한 블록 전후에 동시에 메서드 내에서 동시 코드를 실행할 수 있기 때문에 더 세분화됩니다. 물론 동시 코드를 별도의 비 동기화 메소드로 리팩토링하여 동기화 된 메소드를 쉽게 사용할 수 있습니다. 코드를 이해하기 쉽게 만드는 방법을 사용하십시오.
답변
동기화 된 방법
장점 :
- IDE는 동기화 된 메소드를 표시 할 수 있습니다.
- 구문이 더 간결합니다.
- 동기화 된 블록을 분리하여 메소드를 분리합니다.
단점 :
- 이것과 동기화되므로 외부인도 동기화 할 수 있습니다.
- 동기화 된 블록 외부로 코드를 이동하기가 더 어렵습니다.
동기화 된 블록
장점 :
- 잠금에 개인 변수를 사용하여 잠금을 클래스 내부에 유지하도록 허용합니다.
- 변수에 대한 참조를 검색하여 동기화 된 블록을 찾을 수 있습니다.
단점 :
- 구문이 더 복잡하므로 코드를 읽기가 어렵습니다.
개인적으로 동기화가 필요한 것에 중점을 둔 클래스와 동기화 된 메소드를 사용하는 것을 선호합니다. 이러한 클래스는 가능한 한 작아야하므로 동기화를 쉽게 검토 할 수 있어야합니다. 다른 사람들은 동기화에 신경 쓸 필요가 없습니다.
답변
주요 차이점은 동기화 된 블록을 사용하는 경우이 이외의 다른 객체를 잠그면 훨씬 더 유연해질 수 있다는 것입니다.
메시지 대기열과 여러 메시지 생산자 및 소비자가 있다고 가정합니다. 우리는 제작자가 서로 간섭하는 것을 원하지 않지만 소비자는 제작자를 기다릴 필요없이 메시지를 검색 할 수 있어야합니다. 그래서 우리는 단지 객체를 생성합니다
Object writeLock = new Object();
그리고 지금부터 프로듀서는 새 메시지를 추가하려고 할 때마다 다음과 같이 잠급니다.
synchronized(writeLock){
// do something
}
따라서 소비자는 여전히 읽을 수 있으며 생산자는 잠겨 있습니다.
답변
동기화 된 방법
동기화 된 방법에는 두 가지 효과가 있습니다.
첫째, 하나의 스레드가 객체에 대해 동기화 된 메소드를 실행하는 경우 첫 번째 스레드가 객체와 함께 완료 될 때까지 동일한 객체 블록에 대해 동기화 된 메소드를 호출하는 다른 모든 스레드 (일시 중단).
둘째, 동기화 된 메소드가 종료되면 동일한 오브젝트에 대한 동기화 된 메소드의 후속 호출과 발생 전 관계를 자동으로 설정합니다. 이를 통해 객체 상태에 대한 변경 사항이 모든 스레드에 표시됩니다.
생성자를 동기화 할 수는 없습니다. 생성자와 동기화 된 키워드를 사용하면 구문 오류가 발생합니다. 생성자를 동기화하는 것은 의미가 없습니다. 객체를 생성하는 스레드 만 생성되는 동안 액세스 할 수 있어야하기 때문입니다.
동기화 된 진술
동기화 된 메소드와 달리, 동기화 된 명령문은 고유 잠금을 제공하는 오브젝트를 지정해야합니다. 대부분은 목록 또는 맵에 대한 액세스를 동기화하기 위해이를 사용하지만 오브젝트의 모든 메소드에 대한 액세스를 차단하고 싶지는 않습니다.
Q : 내장 잠금 및 동기화 동기화는 내장 잠금 또는 모니터 잠금이라고하는 내부 엔터티를 중심으로 구축됩니다. (API 사양은 종종이 엔티티를 단순히 “모니터”라고합니다.) 내장 잠금은 동기화의 두 측면에서 중요한 역할을합니다. 즉 객체 상태에 대한 독점 액세스를 강화하고 가시성에 필수적인 관계를 설정합니다.
모든 객체에는 관련된 고유 잠금이 있습니다. 일반적으로 객체 필드에 독점적이고 일관된 액세스가 필요한 스레드는 객체에 액세스하기 전에 객체의 본질적 잠금을 획득 한 다음 완료되면 본질적 잠금을 해제해야합니다. 스레드는 잠금을 획득하고 잠금을 해제 한 시간 사이에 고유 잠금을 소유한다고합니다. 스레드가 내장 잠금을 소유하는 한 다른 스레드는 동일한 잠금을 얻을 수 없습니다. 다른 스레드는 잠금을 획득하려고 시도 할 때 차단됩니다.
package test;
public class SynchTest implements Runnable {
private int c = 0;
public static void main(String[] args) {
new SynchTest().test();
}
public void test() {
// Create the object with the run() method
Runnable runnable = new SynchTest();
Runnable runnable2 = new SynchTest();
// Create the thread supplying it with the runnable object
Thread thread = new Thread(runnable,"thread-1");
Thread thread2 = new Thread(runnable,"thread-2");
// Here the key point is passing same object, if you pass runnable2 for thread2,
// then its not applicable for synchronization test and that wont give expected
// output Synchronization method means "it is not possible for two invocations
// of synchronized methods on the same object to interleave"
// Start the thread
thread.start();
thread2.start();
}
public synchronized void increment() {
System.out.println("Begin thread " + Thread.currentThread().getName());
System.out.println(this.hashCode() + "Value of C = " + c);
// If we uncomment this for synchronized block, then the result would be different
// synchronized(this) {
for (int i = 0; i < 9999999; i++) {
c += i;
}
// }
System.out.println("End thread " + Thread.currentThread().getName());
}
// public synchronized void decrement() {
// System.out.println("Decrement " + Thread.currentThread().getName());
// }
public int value() {
return c;
}
@Override
public void run() {
this.increment();
}
}
동기화 된 방법, 블록 및 동기화없이 서로 다른 출력을 교차 점검합니다.
답변
참고 : 정적 동기화 된 메소드 및 블록은 클래스 오브젝트에서 작동합니다.
public class MyClass {
// locks MyClass.class
public static synchronized void foo() {
// do something
}
// similar
public static void foo() {
synchronized(MyClass.class) {
// do something
}
}
}
답변
Java 컴파일러가 소스 코드를 바이트 코드로 변환하면 동기화 된 메소드와 동기화 된 블록을 매우 다르게 처리합니다.
JVM이 동기화 된 메소드를 실행할 때 실행중인 스레드는 메소드의 method_info 구조에 ACC_SYNCHRONIZED 플래그가 설정되어 있음을 식별 한 후 자동으로 오브젝트의 잠금을 획득하고 메소드를 호출 한 후 잠금을 해제합니다. 예외가 발생하면 스레드가 자동으로 잠금을 해제합니다.
반면에 메소드 블록 동기화는 오브젝트의 잠금 및 예외 처리를 확보하기위한 JVM의 내장 지원을 생략하며 기능을 명시 적으로 바이트 코드로 작성해야합니다. 동기화 된 블록이있는 메소드의 바이트 코드를 읽으면이 기능을 관리하기위한 12 가지 이상의 추가 작업이 표시됩니다.
다음은 동기화 된 메소드와 동기화 된 블록을 생성하기위한 호출을 보여줍니다.
public class SynchronizationExample {
private int i;
public synchronized int synchronizedMethodGet() {
return i;
}
public int synchronizedBlockGet() {
synchronized( this ) {
return i;
}
}
}
이 synchronizedMethodGet()
메소드는 다음 바이트 코드를 생성합니다.
0: aload_0
1: getfield
2: nop
3: iconst_m1
4: ireturn
그리고 synchronizedBlockGet()
메소드 의 바이트 코드는 다음과 같습니다.
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: aload_0
5: getfield
6: nop
7: iconst_m1
8: aload_1
9: monitorexit
10: ireturn
11: astore_2
12: aload_1
13: monitorexit
14: aload_2
15: athrow
동기화 된 방법과 블록의 한 가지 중요한 차이점은 동기화 된 블록은 일반적으로 잠금 범위를 줄입니다. 잠금 범위는 성능에 반비례하기 때문에 항상 중요한 코드 섹션 만 잠그는 것이 좋습니다. 동기화 된 블록을 사용하는 가장 좋은 예 중 하나는 전체를 잠그는 대신 싱글 톤 패턴의 이중 검사 잠금입니다.getInstance()
방법 Singleton 인스턴스를 만드는 데 사용되는 중요한 코드 섹션 만 잠급니다. 잠금은 한두 번만 필요하므로 성능이 크게 향상됩니다.
동기화 된 메소드를 사용하는 동안 정적 동기화 메소드와 비 정적 동기화 메소드를 모두 혼합하는 경우 특별한주의가 필요합니다.