Java 다중 루틴 프로그래밍에서synchronized 키워드의 기초 용법 설명

5638 단어 Javasynchronized
다중 루틴 프로그래밍에서 가장 관건적이고 가장 관심 있는 문제는 동기화 문제이다. 이것은 어려운 점이자 핵심이다.
jdk 최초의 버전인synchronized,volatile에서 jdk 1.5에서 제공하는java까지.util.concurrent.locks 패키지의 Lock 인터페이스(ReadLock, WriteLock, ReentrantLock 구현)는 다중 루틴의 실현도 한 걸음 한 걸음 성숙화되고 있다.
 
동기화, 그것은 어떤 메커니즘을 통해 제어합니까?첫 번째 반응은 자물쇠다. 이것은 운영체제와 데이터베이스를 배울 때 이미 접촉했을 것이다.자바의 다중 루틴 프로그램에서 여러 프로그램이 같은 자원을 경쟁할 때 자원의 부식을 방지하기 위해 첫 번째 자원에 접근하는 루틴에 대상 자물쇠를 분배하고 나중에는 이 대상 자물쇠의 방출을 기다려야 한다.
 
네, 자바 라인의 동기화, 가장 관심 있는 것은 공유 자원의 사용입니다.
 
먼저 어떤 라인의 공유 자원이 있는지 알아보고,
JVM에서 조정해야 하는 스레드 공유 데이터는 다음과 같습니다.
1, 더미에 저장된 실례 변수;2, 메소드 영역에 저장된 클래스 변수.
 
자바 가상 머신이 클래스를 불러올 때 모든 대상이나 클래스는 하나의 모니터와 연결되어 대상의 실례 변수나 클래스 변수를 보호한다.물론 대상에 실례 변수가 없거나 클래스에 변수가 없으면 모니터는 아무것도 감시하지 않는다.
 
위에서 말한 모니터의 상호 배척성을 실현하기 위해 가상 기기는 모든 대상이나 클래스에 하나의 자물쇠(은형 자물쇠라고도 부른다)를 연결했다. 여기서 설명하자면 클래스 자물쇠도 대상 자물쇠를 통해 이루어진다. 클래스가 불러올 때 JVM은 모든 클래스에 자물쇠를 만들기 때문이다.lang. Class의 실례;그래서 대상을 잠그면 이런 종류의 대상을 잠그기도 한다.
 
또한 하나의 라인은 한 대상에 대해 여러 번 자물쇠를 잠글 수 있고 여러 번 방출해야 한다.이것은 JVM을 통해 모든 대상의 자물쇠에 제공되는 lock 계산기입니다. 마지막 자물쇠는 1을 추가하고 해당하는 마이너스 1을 추가합니다. 계산기의 값이 0이면 방출됩니다.이 대상 자물쇠는 JVM 내부의 모니터에서 사용되고 JVM이 자동으로 생성하기 때문에 모든 프로그램원은 스스로 손을 대지 않아도 된다.
 
자바의 동기화 원리를 소개한 후에 우리는 본론으로 들어가서synchronized의 사용을 먼저 이야기하고 다른 동기화는 뒷부분에서 소개할 것이다.
 
먼저 예를 하나 실행해 보세요.

package thread_test; 
 
/** 
 *  Thread  
 * 
 */ 
public class TestThread extends Thread{  
  private int threadnum; 
 
  public TestThread(int threadnum) {  
    this.threadnum = threadnum;  
  } 
   
  @Override 
  public synchronized void run() {  
    for(int i = 0;i<1000;i++){  
          System.out.println("NO." + threadnum + ":" + i ); 
    } 
    }  
   
    public static void main(String[] args) throws Exception {  
      for(int i=0; i<10; i++){ 
          new TestThread(i).start(); 
          Thread.sleep(1); 
      } 
    }  
} 
 
실행 결과:

NO.0:887 
NO.0:888 
NO.0:889 
NO.0:890 
NO.0:891 
NO.0:892 
NO.0:893 
NO.0:894 
NO.7:122 
NO.7:123 
NO.7:124 
위쪽은 단지 하나의 단편일 뿐, 하나의 문제를 설명할 뿐이다.
세심한 아동화는 NO.0:894 뒤에 NO.7:122, 즉 0부터 999까지 따르지 않았다는 것을 발견할 수 있다.
synchronized는 동기화 방법이나 동기화 블록을 실현할 수 있다고 하는데 여기는 왜 안 돼요?
 
먼저 동기화 메커니즘에서 분석하자면 동기화는 자물쇠를 통해 이루어진다. 그러면 위의 예에서 어떤 대상을 잠갔거나 어떤 종류를 잠갔을까?안에 두 개의 변수가 있는데, 하나는 i이고, 하나는threadnum이다.i는 방법 내부이고,threadnum은 사유입니다.
synchronized의 운영 메커니즘에 대해 알아보겠습니다.
자바 프로그램에서synchronized 블록이나synchronized 방법을 사용할 때 이 구역을 감시합니다.JVM은 프로그램을 처리할 때 프로그램이 감시 영역에 들어가면 자동으로 개체나 클래스를 잠그게 됩니다.
 
그러면 위의 예에서synchronized 키워드를 사용한 후에 잠긴 것은 무엇입니까?
synchronized 방법이 있을 때, 잠금 호출 방법의 실례 대상 자체를 대상 잠금으로 합니다.이 예에서 10개의 스레드는 자신이 만든 TestThread의 클래스 대상이 있기 때문에 가져온 대상 자물쇠도 자신의 대상 자물쇠로 다른 스레드와는 아무런 관계가 없습니다.
 
방법 잠금을 실현하려면 공유된 대상을 잠가야 한다.
 
위의 실례를 수정하고 다시 보자.

package thread_test; 
 
/** 
 *  Thread  
 * 
 */ 
public class TestThread extends Thread{  
  private int threadnum; 
  private String flag;  //  
   
  public TestThread(int threadnum,String flag) {  
       this.threadnum = threadnum;  
        this.flag = flag; 
    } 
   
  @Override 
    public void run() {  
    synchronized(flag){ 
      for(int i = 0;i<1000;i++){  
              System.out.println("NO." + threadnum + ":" + i ); 
          }  
    } 
    }  
 
    public static void main(String[] args) throws Exception {  
      String flag = new String("flag"); 
      for(int i=0; i<10; i++){ 
          new TestThread(i,flag).start(); 
          Thread.sleep(1); 
      } 
    }  
} 
 
공유된 로고 플래그를 추가했습니다.그리고synchronized 블록을 통해flag 로고를 동기화합니다.그러면 공유 객체를 잠그는 조건이 충족됩니다.
네, 운행 결과는 이미 순서대로 왔습니다.
동기화 목적을 달성하기 위해synchronized 블록을 지정합니다.그럼 다른 방법이 있을까요?synchronized 방법을 통해 실현할 수 있을까요?
 
동기화의 원리에 따라 공유 대상의 자물쇠나 클래스 자물쇠를 얻을 수 있고 동기화를 실현할 수 있다.그러면 저희가 같은 종류의 자물쇠를 공유해서 할 수 있지 않을까요?
 
네, 우리는 정적 동기화 방법을 사용할 수 있습니다. 정적 방법의 특성에 따라 클래스 대상 자체만 호출할 수 있고 실례화된 클래스 대상을 통해 호출할 수 없습니다.그러면 만약에 이 정적 방법의 자물쇠를 얻게 된다면 바로 이 자물쇠를 얻는 것이다. 이 자물쇠는 모두 TestThread 자물쇠이고 공유 자물쇠를 얻는 목적을 달성한다.
 
구현 코드는 다음과 같습니다.

package thread_test; 
 
/** 
 *  Thread  
 * 
 * @author ciding 
 * @createTime Dec 7, 2011 9:37:25 AM 
 * 
 */ 
public class TestThread extends Thread{  
  private int threadnum; 
   
  public TestThread(int threadnum) {  
    this.threadnum = threadnum;  
  } 
   
  public static synchronized void staticTest(int threadnum) {  
    for(int i = 0;i<1000;i++){  
      System.out.println("NO." + threadnum + ":" + i ); 
    }  
  }  
 
  public static void main(String[] args) throws Exception {  
    for(int i=0; i<10; i++){ 
      new TestThread(i).start(); 
      Thread.sleep(1); 
    } 
  }  
   
  @Override 
  public void run(){ 
    staticTest(threadnum); 
  } 
} 
운행 결과는 두 번째 예와 같다.
 
 
이상의 내용은 주로 두 가지 문제를 설명하는데 그것이 바로 동기화 블록과 동기화 방법이다.
1, 동기화 블록: 가져온 대상 자물쇠는synchronized(flag)의flag 대상 자물쇠입니다.
2, 동기화 방법: 방법이 속하는 클래스 대상과 클래스 대상 자물쇠를 가져옵니다.
정적 동기화 방법은 여러 개의 스레드가 공유되기 때문에 반드시 동기화할 것이다.
정적 동기화 방법이 아니라 단일 모드에서만 동기화됩니다.

좋은 웹페이지 즐겨찾기