다중 스레드 프로그래밍에서 가장 중요한 문제는 동기화 문제가되어야하며, 이는 어려운 지점이자 핵심입니다.
JDK의 초기 버전의 동기화 및 휘발성에서 JDK 1.5에 제공된 java.util.concurrent.locks 패키지의 잠금 인터페이스에 이르기까지 (구현에는 readlock, writelock 및 reentrantlock이 포함됨), 멀티 스레딩 구현도 점진적으로 성숙합니다.
동기화를 제어하기 위해 어떤 메커니즘이 사용됩니까? 첫 번째 반응은 잠금이며 운영 체제와 데이터베이스를 학습 할 때 노출되어야합니다. Java 다중 스레드 프로그램에서, 자원 부식을 방지하기 위해 여러 프로그램이 동일한 리소스를 놓고 경쟁 할 때, 리소스에 액세스하는 첫 번째 스레드에는 객체 잠금이 할당되며, 나중에 세대는이 객체 잠금의 출시를 기다려야합니다.
예, Java 스레드의 동기화에 가장 관심이있는 것은 공유 리소스를 사용하는 것입니다.
먼저 사용할 수있는 스레드의 일부 공유 리소스를 이해해 봅시다.
JVM에서 스레드가 공유하는 데이터를 조정해야합니다.
1. 힙에 저장된 인스턴스 변수; 2. 메소드 영역에 저장된 클래스 변수.
Java Virtual Machine이 클래스를로드하면 각 객체 또는 클래스는 모니터와 연관되어 개체의 인스턴스 변수 또는 클래스 변수를 보호합니다. 물론 객체에 인스턴스 변수가 없거나 클래스에 변수가없는 경우 모니터는 아무 모니터를 모니터링하지 않습니다.
위에서 언급 한 모니터의 뮤트를 달성하기 위해 가상 머신은 각 객체 또는 클래스에 대해 잠금 (보이지 않는 잠금이라고도 함)을 연관시킵니다. 클래스가로드되면 JVM은 각 클래스에 대한 Java.lang.class 인스턴스를 생성하기 때문에 클래스 잠금도 객체 잠금을 통해 구현된다고 설명하겠습니다. 따라서 잠금 장치가 객체에 위배되면이 클래스의 클래스 객체가 잠겨 있습니다.
또한 스레드는 객체를 여러 번 잠글 수 있으며, 이는 여러 릴리스에 해당합니다. 각 객체 잠금에 대해 JVM이 제공하는 잠금 계산기입니다. 마지막 잠금은 1이 추가되고 해당 마이너스 1이 추가되고 계산기 값이 0 인 경우 해제됩니다. 이 객체 잠금은 JVM 내부의 모니터에서 사용되며 JVM에서도 자동으로 생성됩니다. 모든 프로그래머는 스스로 추가 할 필요가 없습니다.
Java의 동기화 원리를 도입 한 후, 우리는 주제를 얻고 먼저 동기화 된 사용에 대해 이야기 할 것입니다. 다른 동기화는 다음 장에서 도입됩니다.
먼저 예제를 실행해 보겠습니다.
패키지 스레드 _test; / *** 스레드 클래스의 구현을 확장하는 다중 스레드 프로그램 테스트**/ public class testthread는 스레드 {private int streldnum; public testthread (int strandnum) {this.threadnum = threadnum; } @override public synchronized void run () {for (int i = 0; i <1000; i ++) {system.out.println ( "no." + stroodnum + ":" + i); }} public static void main (string [] args)은 예외 {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로 시작되지 않음을 의미합니다.
동기화 된 동기화 방법 또는 동기화 블록을 구현할 수 있다고합니다. 왜 여기서 작동 할 수 없는가?
먼저 동기화 메커니즘을 분석하겠습니다. 동기화는 잠금을 통해 달성됩니다. 위의 예에서 어떤 객체가 잠겨 있거나 어떤 클래스가 잠겨 있습니까? 내부에는 두 가지 변수가 있으며, 하나는 I이고 다른 하나는 ThreadNum입니다. 나는이 방법의 내부이며 ThreadNum은 비공개입니다.
동기화 된 실행 메커니즘에 대해 알아 보겠습니다.
Java 프로그램에서 동기화 된 블록 또는 동기화 된 방법이 사용될 때이 영역은 모니터링으로 표시됩니다. JVM이 프로그램을 처리하는 경우 프로그램이 모니터링 영역에 들어가면 자동으로 객체 또는 클래스를 잠그게합니다.
위의 예에서는 동기화 된 키워드가 사용 된 후에 잠긴 내용은 무엇입니까?
동기화 된 메소드가 메소드 자체를 객체 잠금으로 호출하는 인스턴스 객체를 잠그십시오. 이 예에서 10 스레드에는 고유 한 TestThread 클래스 객체가 있으므로 획득 한 객체 잠금 장치도 자체 객체 잠금 장치이며 다른 스레드와 관련이 없습니다.
메소드 잠금을 구현하려면 공유 객체를 잠겨 있어야합니다.
위의 예를 변경 한 다음 다음을 살펴보십시오.
패키지 스레드 _test; / *** 스레드 클래스의 구현을 확장하는 다중 스레드 프로그램 테스트**/ public class testthread는 스레드 {private int streldnum; 개인 문자열 플래그; // mark public testthread (int strooknum, string flag) {this.threadnum = threadnum; this.flag = 플래그; } @override public void run () {synchronized (flag) {for (int i = 0; i <1000; i ++) {system.out.println ( "no." + stroodnum + ":" + i); }}} public static void main (String [] args)은 예외 {string flag = new String ( "flag"); for (int i = 0; i <10; i ++) {new TestThread (i, flag) .start (); Thread.sleep (1); }}}
공유 플래그도 추가됩니다. 그런 다음 플래그 플래그는 동기화 된 블록을 통해 동기화됩니다. 이것은 공유 객체를 잠그는 조건을 충족합니다.
예, 실행 결과가 순서대로 나왔습니다.
동기화 된 블록을 통해 동기화를 달성하기 위해 객체 잠금의 획득을 지정하십시오. 동기화 된 방법을 통해 구현할 수있는 다른 방법이 있습니까?
동기화 원칙에 따라 : 공유 객체 잠금 또는 클래스 잠금을 얻을 수 있다면 동기화를 달성 할 수 있습니다. 그래서 우리는 클래스 잠금을 공유하여 그것을 달성 할 수 있습니까?
예, 정적 동기화 방법을 사용할 수 있습니다. 정적 방법의 특성에 따르면 클래스 객체 자체를 호출 할 수 있으며 클래스 객체를 인스턴스화하여 호출 할 수 없습니다. 그런 다음이 정적 메소드의 잠금을 얻으면 클래스 잠금을 얻고이 클래스 잠금은 모두 테스트 스레드 클래스 잠금 장치이며 공유 클래스 잠금을 얻는 목적이 달성됩니다.
구현 코드는 다음과 같습니다.
패키지 스레드 _test; / ** * 스레드 클래스의 구현을 확장하는 다중 스레드 프로그램 테스트 * * @Author CIDID * @CreateTime 2011 년 12 월 7 일 9:37:25 AM * */ public class testthread는 스레드 {private int stroodnum; public testthread (int strandnum) {this.threadnum = threadnum; } public static synchronized void statictest (int threadnum) {for (int i = 0; i <1000; i ++) {system.out.println ( "no." + stroodnum + ":" + i); }} public static void main (string [] args)은 예외 {for (int i = 0; i <10; i ++) {new TestThread (i) .start (); Thread.sleep (1); }} @override public void run () {statictest (ThreadNum); }} 실행 결과는 두 번째 예제와 동일하게 생략됩니다.
위의 내용은 주로 동기화 블록과 동기화 방법의 두 가지 문제를 설명합니다.
1. 동기화 된 블록 : 획득 된 객체 잠금은 동기화 된 (플래그)의 플래그 객체 잠금입니다.
2. 동기화 방법 : 메소드가 속한 클래스 객체 및 클래스 객체 잠금.
여러 스레드가 공유되므로 정적 동기화 방법은 반드시 동기화됩니다.
정적 동기화 방법 대신 싱글 톤 모드에서만 동기화됩니다.