자바의synchronized 키워드

9069 단어 javasynchronized
Java 언어의 키워드는 하나의 방법이나 코드 블록을 수식할 때 같은 시간에 최대 한 개의 라인만 이 코드를 실행할 수 있도록 보장합니다.
1. 두 개의 병렬 라인이 같은 대상object에 있는synchronized (this) 동기화 코드 블록에 접근할 때 한 시간 안에 한 라인만 실행될 수 있습니다.다른 라인은 현재 라인이 이 코드 블록을 실행한 후에야 이 코드 블록을 실행할 수 있습니다.
2. 그러나, 한 라인이object의synchronized (this) 동기화 코드 블록에 접근할 때, 다른 라인은 이 object의 비synchronized (this) 동기화 코드 블록에 접근할 수 있다.
3. 특히 관건적인 것은, 하나의 라인이object의synchronized(this) 동기화 코드 블록에 접근할 때, 다른 라인이object의 모든 다른synchronized(this) 동기화 코드 블록에 대한 접근이 막힐 것이다.
넷째, 세 번째 예는 다른 동기화 코드 블록에도 적용된다.즉, 하나의 라인이object의synchronized (this) 동기화 코드 블록에 접근할 때, 이object의 대상 자물쇠를 얻을 수 있다.결과적으로 다른 라인이 이object 대상의 모든 동기화 코드 부분에 대한 접근이 일시적으로 막혔습니다.
5. 상기 규칙은 다른 대상의 자물쇠에도 적용된다.
예제 설명:
1. 두 개의 병렬 라인이 같은 대상object에 있는synchronized (this) 동기화 코드 블록에 접근할 때 한 시간 안에 한 라인만 실행될 수 있습니다.다른 라인은 현재 라인이 이 코드 블록을 실행한 후에야 이 코드 블록을 실행할 수 있습니다.

package ths;

public class Thread1 implements Runnable { 
   public void run() { 
     synchronized(this) { 
        for (int i = 0; i < 5; i++) { 
          System.out.println(Thread.currentThread().getName() + " synchronized loop " + i); 
        } 
     } 
   } 
   public static void main(String[] args) { 
     Thread1 t1 = new Thread1(); 
     Thread ta = new Thread(t1, "A"); 
     Thread tb = new Thread(t1, "B"); 
     ta.start(); 
     tb.start(); 
   } 
}

결과:
     A synchronized loop 0 
     A synchronized loop 1 
     A synchronized loop 2 
     A synchronized loop 3 
     A synchronized loop 4 
     B synchronized loop 0 
     B synchronized loop 1 
     B synchronized loop 2 
     B synchronized loop 3 
     B synchronized loop 4
2. 그러나, 한 라인이object의synchronized (this) 동기화 코드 블록에 접근할 때, 다른 라인은 이 object의 비synchronized (this) 동기화 코드 블록에 접근할 수 있다.

package ths;

public class Thread2 { 
   public void m4t1() { 
     synchronized(this) { 
        int i = 5; 
        while( i-- > 0) { 
          System.out.println(Thread.currentThread().getName() + " : " + i); 
          try { 
             Thread.sleep(500); 
          } catch (InterruptedException ie) { 
          } 
        } 
     } 
   } 
   public void m4t2() { 
     int i = 5; 
     while( i-- > 0) { 
        System.out.println(Thread.currentThread().getName() + " : " + i); 
        try { 
          Thread.sleep(500); 
        } catch (InterruptedException ie) { 
        } 
     } 
   } 
   public static void main(String[] args) { 
     final Thread2 myt2 = new Thread2(); 
     Thread t1 = new Thread( new Runnable() { public void run() { myt2.m4t1(); } }, "t1" ); 
     Thread t2 = new Thread( new Runnable() { public void run() { myt2.m4t2();  } }, "t2" ); 
     t1.start(); 
     t2.start(); 
   } 
}

결과:
     t1 : 4 
     t2 : 4 
     t1 : 3 
     t2 : 3 
     t1 : 2 
     t2 : 2 
     t1 : 1 
     t2 : 1 
     t1 : 0 
     t2 : 0
3. 특히 관건적인 것은, 하나의 라인이object의synchronized(this) 동기화 코드 블록에 접근할 때, 다른 라인이object의 모든 다른synchronized(this) 동기화 코드 블록에 대한 접근이 막힐 것이다.
Thread2 수정하기2.m4t2() 메서드:

 public void m4t2() { 
     synchronized(this) { 
        int i = 5; 
        while( i-- > 0) { 
          System.out.println(Thread.currentThread().getName() + " : " + i); 
          try { 
             Thread.sleep(500); 
          } catch (InterruptedException ie) { 
          } 
        } 
     }

   }

결과:
     t1 : 4 
     t1 : 3 
     t1 : 2 
     t1 : 1 
     t1 : 0 
     t2 : 4 
     t2 : 3 
     t2 : 2 
     t2 : 1 
     t2 : 0
넷째, 세 번째 예는 다른 동기화 코드 블록에도 적용된다.즉, 하나의 라인이object의synchronized (this) 동기화 코드 블록에 접근할 때, 이object의 대상 자물쇠를 얻을 수 있다.결과적으로 다른 라인이 이object 대상의 모든 동기화 코드 부분에 대한 접근이 일시적으로 막혔습니다.
Thread2 수정하기2.m4t2() 방법은 다음과 같습니다.

public synchronized void m4t2() { 
     int i = 5; 
     while( i-- > 0) { 
        System.out.println(Thread.currentThread().getName() + " : " + i); 
        try { 
          Thread.sleep(500); 
        } catch (InterruptedException ie) { 
        } 
     } 
   }
결과:
     t1 : 4 
     t1 : 3 
     t1 : 2 
     t1 : 1 
     t1 : 0 
     t2 : 4 
     t2 : 3 
     t2 : 2 
     t2 : 1 
     t2 : 0
5. 상기 규칙은 다른 객체 잠금에도 적용됩니다.

package ths;

public class Thread3 { 
   class Inner { 
     private void m4t1() { 
        int i = 5; 
        while(i-- > 0) { 
          System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i); 
          try { 
             Thread.sleep(500); 
          } catch(InterruptedException ie) { 
          } 
        } 
     } 
     private void m4t2() { 
        int i = 5; 
        while(i-- > 0) { 
          System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i); 
          try { 
             Thread.sleep(500); 
          } catch(InterruptedException ie) { 
          } 
        } 
     } 
   } 
   private void m4t1(Inner inner) { 
     synchronized(inner) { //  
     inner.m4t1(); 
   } 
   private void m4t2(Inner inner) { 
     inner.m4t2(); 
   } 
   public static void main(String[] args) { 
     final Thread3 myt3 = new Thread3(); 
     final Inner inner = myt3.new Inner(); 
     Thread t1 = new Thread( new Runnable() {public void run() { myt3.m4t1(inner);} }, "t1"); 
   Thread t2 = new Thread( new Runnable() {public void run() { myt3.m4t2(inner);} }, "t2"); 
   t1.start(); 
   t2.start(); 
 } 
}

결과:
비록 스레드 t1은 Inner에 대한 대상 자물쇠를 얻었지만, 스레드 t2는 같은 Inner의 비동기적인 부분을 방문하기 때문이다.그래서 두 라인은 서로 방해하지 않는다.
     t1 : Inner.m4t1()=4 
     t2 : Inner.m4t2()=4 
     t1 : Inner.m4t1()=3 
     t2 : Inner.m4t2()=3 
     t1 : Inner.m4t1()=2 
     t2 : Inner.m4t2()=2 
     t1 : Inner.m4t1()=1 
     t2 : Inner.m4t2()=1 
     t1 : Inner.m4t1()=0 
     t2 : Inner.m4t2()=0
지금 이너에 있어요.m4t2() 앞에 synchronized:

 private synchronized void m4t2() { 
     int i = 5; 
     while(i-- > 0) { 
        System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i); 
        try { 
          Thread.sleep(500); 
        } catch(InterruptedException ie) { 
        } 
     } 
   }
결과:
비록 루트 t1과 t2는 같은 Inner 대상 중 두 개의 상관없는 부분을 방문했지만 t1은 먼저 Inner에 대한 대상 자물쇠를 얻었기 때문에 t2는 Inner에 대한 자물쇠를 얻었다.m4t2()의 접근도 막혔다. 왜냐하면 m4t2()는 Inner의 동기화 방법이기 때문이다.
     t1 : Inner.m4t1()=4 
     t1 : Inner.m4t1()=3 
     t1 : Inner.m4t1()=2 
     t1 : Inner.m4t1()=1 
     t1 : Inner.m4t1()=0 
     t2 : Inner.m4t2()=4 
     t2 : Inner.m4t2()=3 
     t2 : Inner.m4t2()=2 
     t2 : Inner.m4t2()=1 
     t2 : Inner.m4t2()=0
synchronized 키워드, 두 가지 용법을 포함합니다:synchronized 방법과synchronized 블록. 
1.synchronized 방법: 방법 성명에 synchronized 키워드를 넣어synchronized 방법을 설명합니다.예:
public synchronized void accessVal(int newVal); 
synchronized 방법은 클래스 구성원 변수에 대한 접근을 제어합니다. 모든 클래스는 하나의 자물쇠에 대응하고, 모든 synchronized 방법은 반드시 이 방법을 호출하는 클래스 실례의 자물쇠를 얻어야 실행할 수 있습니다. 그렇지 않으면 소속 루트가 막힙니다. 방법이 실행되면 이 자물쇠를 독점하고 이 방법에서 돌아올 때까지 자물쇠를 방출합니다. 이후에 막힌 루트는 이 자물쇠를 얻어서 다시 실행 가능한 상태로 들어갈 수 있습니다.이러한 메커니즘은 같은 시각에 모든 클래스 실례에 대해synchronized라고 성명된 구성원 함수 중 하나는 실행 가능한 상태이기 때문에 (이 클래스 실례에 대응하는 자물쇠를 얻을 수 있기 때문에) 클래스 구성원 변수의 접근 충돌을 효과적으로 피할 수 있다. (클래스 구성원 변수에 접근할 수 있는 모든 방법이 synchronized라고 성명된다면) 
자바에서 클래스의 실례뿐만 아니라 모든 클래스도 자물쇠에 대응한다. 그러면 우리는 클래스의 정적 구성원 함수를synchronized로 성명하여 클래스의 정적 구성원 변수에 대한 접근을 제어할 수 있다. 
synchronized 방법의 결함: 만약에 큰 방법을synchronized라고 성명하면 효율에 큰 영향을 줄 수 있다. 전형적으로 라인 클래스의 방법run()을synchronized라고 성명하면 라인의 전체 생명 기간 동안 계속 실행되기 때문에 이 클래스의synchronized 방법에 대한 호출은 영원히 성공하지 못할 것이다.물론 우리는 접근 클래스 구성원 변수의 코드를 전문적인 방법에 넣어synchronized라고 설명하고 주 방법에서 호출해서 이 문제를 해결할 수 있지만, 자바는 우리에게 더 좋은 해결 방법을 제공했다. 그것이 바로synchronized 블록이다. 
2.synchronized 블록:synchronized 키워드를 통해synchronized 블록을 설명합니다.구문은 다음과 같습니다.
synchronized(syncObject) { 
//액세스 제어 코드

synchronized 블록은 이러한 코드 블록이다. 그 중의 코드는 대상synchObject(전에서 말한 바와 같이 클래스 실례나 클래스일 수 있음)의 자물쇠를 얻어야 실행할 수 있고 구체적인 메커니즘은 앞에서 말한 것과 같다.임의의 코드 블록에 대해 임의로 지정할 수 있고 잠긴 대상을 임의로 지정할 수 있기 때문에 유연성이 비교적 높다. 
이상은 자바synchronized 키워드에 대한 상세한 실례 소개입니다. 여러분이synchronized 키워드의 사용법을 더욱 잘 배울 수 있도록 도와주시기 바랍니다.

좋은 웹페이지 즐겨찾기