Java 스레드 동기화 상세 정보

Java 스레드 동기화는 근본적으로 하나의 논리에 부합해야 한다: 자물쇠 추가 ------> 수정 ------> 자물쇠 해제
1. 코드 블록 동기화
예는 다음과 같습니다.

public class SyncBlock {
  static class DataWrap {
    int i;
  }
  
  static class SyncBlockThread extends Thread {
    private DataWrap date;
    
    public SyncBlockThread(DataWrap dataWrap) {
      this.date = dataWrap;
    }
    
    @Override
    public void run() {
      
      for (int i = 0; i < 10; i++) {
        synchronized (date) {
          date.i++;
          try {
            sleep(1);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          System.out.println(getName() + " " + date.i);
        }
      }
    }
  }
  
  public static void main(String[] args) {
    // i 
    DataWrap dataWrap = new DataWrap();
    
    new SyncBlockThread(dataWrap).start();
    new SyncBlockThread(dataWrap).start();
    new SyncBlockThread(dataWrap).start();
  }

}

예시에서 순서대로 정수를 출력하기를 희망합니다.
일반적으로 동기화 코드 블록은 잠금이 필요한 대상입니다. 일반적으로 병렬 접근이 필요한 공유 자원입니다. 모든 라인은 지정한 자원을 수정하기 전에 먼저 이 자원을 잠그고 잠금 기간에 다른 라인은 이 자원을 수정할 수 없습니다.이로써 라인의 안전성을 확보하였다.또한 슬립이나 yield를 호출할 때 자원 자물쇠를 양보하지 않습니다.
2. 동기화 방법

public class SyncMethod {
  
  static class DataWrap{
    int i;
    
    public synchronized void valueGrow(){
      i++;
      
      try {
        Thread.sleep(1);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      System.out.println(Thread.currentThread().getName() + " " + i);
    }
  }
  
  static class SyncMethodThread extends Thread {
    DataWrap dataWrap;
    
    public SyncMethodThread(DataWrap dataWrap){
      this.dataWrap = dataWrap;
    }
    
    @Override
    public void run() {
      for (int i = 0; i < 10; i++) {
        dataWrap.valueGrow();  
      }
    }
  }
  
  public static void main(String[] args) {
    // Datawrap i
    
    DataWrap dataWrap = new DataWrap();
    
    new SyncMethodThread(dataWrap).start();
    new SyncMethodThread(dataWrap).start();
    new SyncMethodThread(dataWrap).start();
  }

}

동기화 방법은synchronized 키워드로 수식된 어떤 방법이다. 동기화 방법은 이 대상 자체를 잠그기 때문에 한 라인이 특정한 대상의 동기화 방법을 호출한 후에 다른 라인이 이 대상의 다른 동기화 방법을 호출할 경우에도 이 대상의 자물쇠가 잠겨 있기 때문에 방출되기를 기다려야 한다.
3. 동기식 잠금
동기화 잠금 객체를 정의하여 동기화를 수행하는 경우 동기화 잠금은 Lock 객체로 충당됩니다.

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SyncLock {

  static class DataWrap{
    Lock lock = new ReentrantLock();
    int i;
    
    public void valueGrow(){
      lock.lock();
      try {
        i++;
        
        try {
          Thread.sleep(1);
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " " + i);  
      } finally {
        lock.unlock();
      }
      
    }
  }
  
  static class SyncLockThread extends Thread {
    DataWrap dataWrap;
    
    public SyncLockThread(DataWrap dataWrap){
      this.dataWrap = dataWrap;
    }
    
    @Override
    public void run() {
      for (int i = 0; i < 10; i++) {
        dataWrap.valueGrow();  
      }
    }
  }
  
  public static void main(String[] args) {
    // Datawrap i
    
    DataWrap dataWrap = new DataWrap();
        
    new SyncLockThread(dataWrap).start();
    new SyncLockThread(dataWrap).start();
    new SyncLockThread(dataWrap).start();
  }

}

자물쇠 대상을 사용하여 스레드 동기화를 실현하면 더욱 유연할 수 있다. 일부 자물쇠는 특정한 기능을 가지고 있는데 그 중에서 비교적 자주 사용하는 ReadWriteLock 읽기와 쓰기 자물쇠, ReentrantLock은 자물쇠를 다시 넣을 수 있다.

좋은 웹페이지 즐겨찾기