>Java >java지도 시간 >Java 동기화 코드 블록에 대한 자세한 예제 코드 소개

Java 동기화 코드 블록에 대한 자세한 예제 코드 소개

黄舟
黄舟원래의
2017-02-28 10:47:182290검색

Java 동기화 블록은 메소드 또는 코드 블록을 동기화합니다. 정적 조건을 피하기 위해 Java 동기화 블록을 사용할 수 있습니다. Java의 동기화된 블록은 동기화된 키워드를 사용하여 표시됩니다. Java의 동기화 블록은 일부 객체에서 동기화됩니다. 모든 객체에서 동기화된 모든 동기화 블록은 동시에 하나의 스레드에서만 실행될 수 있습니다. 동기화된 블록에 들어가려는 다른 모든 스레드는 동기화된 블록 내부의 스레드가 블록을 떠날 때까지 차단됩니다.

동기화 키워드는 네 가지 다른 유형의 블록을 표시하는 데 사용할 수 있습니다.

인스턴스 방법


정적 메서드

  1. 인스턴스 메서드의 코드 블록

  2. 정적 메서드의 코드 블록

  3. 이러한 블록은 서로 다른 개체에서 동기화됩니다. 필요한 동기화 블록 유형은 특정 시나리오에 따라 다릅니다.

  4. 동기화된 인스턴스 메서드

예는 다음과 같습니다.

  public synchronized void add(int value){
      this.count += value;
  }

메서드 life에서 동기화 키워드 사용에 유의하세요. . 이는 Java에게 이 메소드가 동기화되었음을 알려줍니다. Java의 동기화된 인스턴스 메소드는 이 메소드에 속한 인스턴스 객체에서 동기화됩니다. 따라서 각 인스턴스에는 다른 개체, 즉 자체 인스턴스에서 동기화되는 동기화 방법이 있습니다. 오직 하나의 스레드만이 인스턴스 동기화 메서드를 실행할 수 있으며, 그 다음 하나의 스레드는 한 번에 하나씩 동기화된 인스턴스 메서드를 실행할 수 있습니다. 인스턴스당 하나의 스레드.

동기화된 정적 메서드

정적 메서드는 동기화 키워드를 사용하는 인스턴스 메서드와 마찬가지로 동기화됨으로 표시됩니다. 예는 다음과 같습니다.

  public static synchronized void add(int value){
      count += value;
  }

여기에는 이 메소드가 동기화되었음을 Java에 알리는 동기화 키워드도 있습니다. 동기화된 정적 메서드는 해당 정적 메서드가 속한 클래스의 클래스 객체에 대해 동기화됩니다. JVM(Java Virtual Machine)의 각 클래스에는 하나의 클래스 객체만 존재하므로 동일한 클래스의 동기화된 정적 메서드는 하나의 스레드만 실행할 수 있습니다. 이 정적 동기화 메서드가 다른 클래스에 있는 경우 스레드는 각 클래스의 내부 정적 동기화 메서드를 실행할 수 있습니다. 호출하는 정적 동기화 방법에 관계없이 각 클래스의 스레드입니다.

인스턴스 메서드의 동기화된 블록

전체 메서드를 동기화할 수는 없습니다. 때로는 메서드의 일부를 동기화하는 것이 더 나을 때도 있습니다. 메소드 내부의 Java 동기화 블록이 이를 가능하게 합니다.

예는 다음과 같습니다.

  public void add(int value){

    synchronized(this){
       this.count += value;   
    }
  }

이 예는 Java 동기화 블록을 사용하여 동기화되는 코드 블록을 구성합니다. 동기식 메서드인 경우 이 메서드가 실행됩니다.

이 Java 동기화 블록이 객체의 일부로 구성되는 방식에 유의하세요. 이 예에서는 호출되는 add 메소드의 인스턴스인 "this"가 사용됩니다. 동기화를 통해 생성된 수용 괄호 안의 객체를 모니터 객체라고 합니다. 이 코드에서는 모니터 개체가 동기적이라고 가정합니다. 동기화된 인스턴스 메서드는 자신이 속한 개체를 감시 개체로 사용합니다.

동일한 모니터링 개체의 Java 동기화 블록에서는 하나의 스레드만 실행할 수 있습니다.


다음 두 인스턴스는 호출된 인스턴스에서 동기화됩니다. 따라서 둘은 동일합니다.

  public class MyClass {
  
    public synchronized void log1(String msg1, String msg2){
       log.writeln(msg1);
       log.writeln(msg2);
    }

  
    public void log2(String msg1, String msg2){
       synchronized(this){
          log.writeln(msg1);
          log.writeln(msg2);
       }
    }
  }

따라서 이 예에서는 하나의 스레드만 두 개의 동기화된 블록 중 하나를 실행할 수 있습니다.

이를 위해 다른 개체에 동기화되는 두 번째 동기화 블록이 있으며 스레드는 한 번에 하나의 내부 메서드만 실행할 수 있습니다.


정적 메서드의 동기화된 블록


다음은 정적 메서드와 동일한 두 가지 인스턴스입니다. 이러한 메서드는 이 메서드가 속한 클래스의 클래스 개체에서 동기화됩니다.

  public class MyClass {

    public static synchronized void log1(String msg1, String msg2){
       log.writeln(msg1);
       log.writeln(msg2);
    }

  
    public static void log2(String msg1, String msg2){
       synchronized(MyClass.class){
          log.writeln(msg1);
          log.writeln(msg2);  
       }
    }
  }

단 하나의 스레드만 두 메서드 중 하나를 동시에 실행할 수 있습니다. MyClass.class에 대해 다른 개체에서 동기화되는 두 번째 동기화 블록이 있으며 스레드는 동시에 하나의 내부 메서드만 실행할 수 있습니다.

Java 동기화 인스턴스


여기 두 스레드를 시작하는 인스턴스가 있으며 둘 다 동일한 Counter 인스턴스의 add 메소드를 호출합니다. 한 번에 하나의 스레드만 동일한 인스턴스의 add 메소드를 호출할 수 있습니다. 이 메소드는 자신이 속한 인스턴스에서 동기화되기 때문입니다.

  public class Counter{
     
     long count = 0;
    
     public synchronized void add(long value){
       this.count += value;
     }
  }

  public class CounterThread extends Thread{

     protected Counter counter = null;

     public CounterThread(Counter counter){
        this.counter = counter;
     }

     public void run() {
	for(int i=0; i<10; i++){
           counter.add(i);
        }
     }
  }

  public class Example {

    public static void main(String[] args){
      Counter counter = new Counter();
      Thread  threadA = new CounterThread(counter);
      Thread  threadB = new CounterThread(counter);

      threadA.start();
      threadB.start(); 
    }
  }

두 개의 스레드가 생성됩니다. 두 개의 동일한 Counter 인스턴스가 해당 생성자에 전달됩니다. add 메서드는 인스턴스 메서드이고 동기화됨으로 표시되므로 add 메서드는 인스턴스에서 동기화됩니다. 따라서 한 번에 하나의 스레드만 이 add 메소드를 호출할 수 있습니다. 다른 스레드는 첫 번째 스레드가 실행되기 전에 add 메소드를 떠날 때까지 기다립니다.


두 개의 스레드가 두 개의 별도 Counter 인스턴스를 참조하는 경우 add 메서드를 동시에 호출하는 데 문제가 없습니다. 이 호출은 다른 개체에 대한 것이므로 이 메서드 호출은 다른 개체(이 메서드에 속한 개체)에서도 동기화됩니다. 따라서 이 호출은 차단되지 않습니다. 예는 다음과 같습니다.

  public class Example {

    public static void main(String[] args){
      Counter counterA = new Counter();
      Counter counterB = new Counter();
      Thread  threadA = new CounterThread(counterA);
      Thread  threadB = new CounterThread(counterB);

      threadA.start();
      threadB.start(); 
    }
  }

注意这两个线程,他们不再引用相同的实例。counterA和counterB的add方法同步在它们自己的实例上。因此不会堵塞。

Java并发工具

这个synchronized机制是java的第一个途径对于访问同步访问被多线程共享的对象。但是这个synchronized机制不是最高级的。那就是为什么Java 5提供了一个并发工具类的集合去帮助开发者实现更细粒度的并发控制相对于synchronized而言。


 以上就是Java同步代码块的详细实例代码介绍的内容,更多相关内容请关注PHP中文网(www.php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.