>  기사  >  Java  >  Java 스레드 동기화 및 동기화 방법에 대한 자세한 설명

Java 스레드 동기화 및 동기화 방법에 대한 자세한 설명

Y2J
Y2J원래의
2017-05-04 09:59:311738검색

이 글에서는 주로 Java 스레드를 예제를 통해 소개합니다: 스레드 동기화-동기화 방법이 필요한 친구가 참조할 수 있습니다

스레드 동기화는 경쟁 리소스에 대한 멀티 스레드 안전접근을 보장하기 위한 것입니다. 수단.

스레드 동기화는 Java 멀티스레드 프로그래밍의 어려움입니다. 개발자는 종종 경쟁 리소스가 무엇인지, 동기화를 고려해야 하는 시기, 동기화 방법 등을 이해하지 못합니다. , 이러한 문제 명확한 답은 없지만 고려해야 할 몇 가지 원칙적인 문제가 동시에 수정되고 있습니까?

동기화를 위해서는 특정 Java 코드에서 다음 두 작업을 완료해야 합니다.

액세스 경쟁 리소스를 비공개로 표시합니다.

변수를 수정하는 코드를 동기화하려면 동기화된 키워드를 사용하여 메서드나 코드를 동기화하세요.

물론 이것이 동시성 안전을 제어하는 ​​유일한 방법은 아닙니다.

동기화 키워드

synchronized 사용 지침은 추상이 아닌 메소드만 표시할 수 있으며 멤버 변수를 식별할 수 없습니다.

동기화 방식의 활용을 실증하기 위해 초기 신용 한도가 100만인 신용카드 계좌를 구축한 후 당좌 대월, 예금 등의 다중 작업을 시뮬레이션했습니다. 분명히 은행 계좌 User 객체는 경쟁 리소스이며 계좌 메소드 oper(int x)는 여러 동시 작업에 사용됩니다. 물론 이 메소드에 동기화가 추가되어야 하며 계좌의 잔액도 필요합니다.

직접 접근은 금지되어 있습니다.

/** 
* Java线程:线程的同步 
* 
* @author leizhimin 2009-11-4 11:23:32 
*/ 
public class Test { 
  public static void main(String[] args) { 
    User u = new User("张三", 100); 
    MyThread t1 = new MyThread("线程A", u, 20); 
    MyThread t2 = new MyThread("线程B", u, -60); 
    MyThread t3 = new MyThread("线程C", u, -80); 
    MyThread t4 = new MyThread("线程D", u, -30); 
    MyThread t5 = new MyThread("线程E", u, 32); 
    MyThread t6 = new MyThread("线程F", u, 21); 
    t1.start(); 
    t2.start(); 
    t3.start(); 
    t4.start(); 
    t5.start(); 
    t6.start(); 
  } 
} 
class MyThread extends Thread { 
  private User u; 
  private int y = 0; 
   MyThread(String name, User u, int y) { 
    super(name); 
    this.u = u; 
    this.y = y; 
  } 
  public void run() { 
    u.oper(y); 
  } 
} 
class User { 
  private String code; 
  private int cash; 
  User(String code, int cash) { 
    this.code = code; 
    this.cash = cash; 
  } 
  public String getCode() { 
    return code; 
  } 
  public void setCode(String code) { 
    this.code = code; 
  } 
  /** 
   * 业务方法 
   * @param x 添加x万元 
   */ 
  public synchronized void oper(int x) { 
    try { 
      Thread.sleep(10L); 
      this.cash += x; 
      System.out.println(Thread.currentThread().getName() + "运行结束,增加“" + x + "”,当前用户账户余额为:" + cash); 
      Thread.sleep(10L); 
    } catch (InterruptedException e) { 
      e.printStackTrace(); 
    } 
  } 
  @Override 
  public String toString() { 
    return "User{" + 
        "code='" + code + '\'' + 
        ", cash=" + cash + 
        '}'; 
  } 
}

출력 결과:

线程A运行结束,增加“20”,当前用户账户余额为:120 
线程F运行结束,增加“21”,当前用户账户余额为:141 
线程E运行结束,增加“32”,当前用户账户余额为:173 
线程C运行结束,增加“-80”,当前用户账户余额为:93 
线程B运行结束,增加“-60”,当前用户账户余额为:33 
线程D运行结束,增加“-30”,当前用户账户余额为:3

부정 교육 자료, 동기화되지 않은 상황, 즉 oper(int x) 메소드의 동기화 수정자를 제거합니다. , 그리고 프로그램을 실행하면 다음과 같습니다.

线程A运行结束,增加“20”,当前用户账户余额为:61 
线程D运行结束,增加“-30”,当前用户账户余额为:63 
线程B运行结束,增加“-60”,当前用户账户余额为:3 
线程F运行结束,增加“21”,当前用户账户余额为:61 
线程E运行结束,增加“32”,当前用户账户余额为:93 
线程C运行结束,增加“-80”,当前用户账户余额为:61

분명히 위의 결과는 잘못된 것입니다. 오류의 원인은 여러 스레드가 동시에 경쟁 리소스 u에 액세스하고 u속성이 변경되었습니다.

동기화의 중요성을 알 수 있습니다.


참고:

이전 기사에서 볼 수 있듯이

스레드가 동기화 메서드를 종료하면 메서드가 속한 개체의 잠금이 해제됩니다. 그러나 특정 메서드를 사용하여 동기화 메서드에서 스레드를 예약할 수도 있습니다. 이러한 메소드는 java.lang.Object 클래스에서 제공됩니다.

void notify()  
     唤醒在此对象监视器上等待的单个线程。  
void notifyAll()  
     唤醒在此对象监视器上等待的所有线程。  
void wait()  
     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。  
void wait(long timeout)  
     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。  
void wait(long timeout, int nanos)  
     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量

위의 방법을 결합하여 멀티스레드 동기화 및 상호 배제 문제를 처리하는 것이 매우 중요합니다. 유명한 생산자-소비자 예는 모든 분야에서 멀티스레딩의 고전적인 예이자 꼭 배워야 할 예입니다. 언어.

위 내용은 Java 스레드 동기화 및 동기화 방법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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