0. 스레드 동기화와 관련하여 (1) 멀티 스레딩을 동기화 해야하는 이유는 무엇입니까?
스레드 동기화는 여러 실행 스레드가 함께 잘 협력하여 여러 스레드가 필요에 따라 자원을 합리적으로 차지하고 릴리스 할 수 있도록합니다. 이 목표를 달성하기 위해 Java의 동기화 코드 블록 및 동기화 방법을 사용합니다. 예를 들어, 멀티 스레드 고정 된 주문 실행 문제를 해결하십시오.
public class twothreadtest {public static void main (String [] args) {Thread th1 = new Mythread1 (); 스레드 th2 = new Mythread2 (); th1.start (); th2.start (); }} class mythread2 스레드 {@override public void run () {for (int i = 0; i <10; i ++) 시스템을 확장합니다. out.println ( "스레드 1 카운터 :"+i); }} class mythread1은 스레드 {@override public void run () {for (int i = 0; i <10; i ++) 시스템을 확장합니다. out.println ( "스레드 1 카운터 :"+i); }} class mythread1은 스레드 {@override public void run () {for (int i = 0; i <10; i ++) 시스템을 확장합니다. out.println ( "스레드 2 카운터 :"+i); }}이 상태에서 멀티 스레드 실행의 결과는 wall의 실행을 무작위로 삽입하는 것입니다. 이는 전적으로 JVM의 스레드 스케줄링에 따라 다릅니다. 질서 정연한 실행이 필요한 경우에,이 임의의 실행 상태는 분명히 부적합합니다.
공개 클래스 스레드 테스트 {public static void main (string [] args) {mythread 스레드 = new Mythread (); 스레드 th1 = 새 스레드 (스레드); 스레드 th2 = 새 스레드 (스레드); th1.start (); th2.start (); }} Class Mythread는 runnable {@override public synchronized void run () {for (int i = 0; i <10; i ++) 시스템을 구현합니다. out.println (thread. currentthread (). getName ()+"counter :"+i); }}동기화 방법을 사용한 후에는 실행 본체 객체를 독점적으로 점유하기 위해 스레드를 제어 할 수 있습니다. 이러한 방식으로 실행 프로세스 중에 스레드는 실행 본체의 작업을 한 번에 실행하고 잠금 상태를 종료 할 수 있습니다. 그런 다음 JVM은 다른 스레드를 발송하여 실행 본체에서 작업을 한 번에 실행합니다.
(2) 스레드 생성 및 실행에 대한 패러다임 :
과거에는 스레드 생성 및 실행을위한 자체 프로그래밍 패러다임도있었습니다. 일반적으로 run () 메소드를 다시 작성하기 위해 실행 클래스를 정의했지만이 방법은 실행 본체와 실행 된 작업을 정리하여 소프트웨어 엔지니어링의 관점에서 분리하는 데 도움이되지 않습니다. 스레드의 실행은 스레드가 실행 객체를 통해 객체의 작업을 실행한다는 것을 의미합니다. 이러한 관점에서, 실행 클래스에서 작업의 처방자를 분리하면 다중 스레드 프로그래밍의 다양한 역할을 명확하게 만들어서 우수한 분리를 얻을 수 있습니다. 다음은 스레드 생성 및 실행을위한 프로그래밍 패러다임입니다.
public class formalthreadclass {public static void main (string [] args) {스레드 스레드 = 새 스레드 (new myrunnable ()); thread.start (); }} 클래스 myrunnable emplements runnable {mytask mytask = new Mytask (); @override public void run () {mytask.dotask (); }} class mytask {public void dotask () {시스템. out.println ( "이것은 실제 작업입니다"); }}
1. 동기화 된 원리
Java에서 각 객체에는 하나의 동기화 잠금 만 가지고 있으며 있습니다. 이것은 또한 객체에 동기화 잠금이 존재 함을 의미합니다.
객체의 동기화 된 메소드를 호출하면 객체의 동기화 잠금을 얻습니다. 예를 들어, Synchronized (OBJ)는 "OBJ 객체"의 동기화 잠금을 획득합니다.
다른 스레드에 의한 동기화 잠금에 대한 액세스는 상호 배타적입니다. 다시 말해, 특정 시점에서 객체의 동기화 잠금은 하나의 스레드로만 얻을 수 있습니다! 동기화 잠금을 통해 여러 스레드에서 "객체/메소드"에 대한 상호 배타적 인 액세스를 얻을 수 있습니다. 예를 들어, 이제 두 개의 스레드 A와 스레드 B가 있으며,이 두 스레드 B는 "객체 OBJ의 동기 잠금"에 액세스합니다. 어느 시점에서 Thread A가 "OBJ의 동기화 잠금"을 획득하고 일부 작업을 수행한다고 가정하십시오. 이때 스레드 B는 또한 "OBJ의 동기화 잠금"을 획득하려고 시도합니다. - 스레드 B는 획득하지 못하고 스레드 A가 "OBJ의 동기화 잠금 잠금"을 릴리스 할 때까지 기다려야하며 실행할 수 있습니다.
2. 동기화 된 기본 규칙
우리는 다음 3에 동기화 된 기본 규칙을 요약하고 예를 통해 설명합니다.
제 1 조 : 스레드가 "특정 객체"의 "동기화 된 메소드"또는 "동기화 된 코드 블록"에 액세스하면 다른 스레드는 "동기화 된 메소드"또는 "객체"의 "동기화 된 코드 블록"에 대한 액세스에서 차단됩니다.
제 2 조 : 스레드가 "특정 객체"의 "동기화 된 메소드"또는 "동기화 된 코드 블록"에 액세스 할 때 다른 스레드는 여전히 "이 개체"의 비동기 코드 블록에 액세스 할 수 있습니다.
제 3 조 : 스레드가 "특정 객체"의 "동기화 된 메소드"또는 "동기화 된 코드 블록"에 액세스하면 다른 스레드는 "객체"의 다른 "동기화 된 메소드"또는 "동기화 된 코드 블록"에 액세스하지 못하게됩니다.
(1) 제 1 조 :
스레드가 "특정 객체"의 "동기화 된 메소드"또는 "동기화 된 코드 블록"에 액세스하면 다른 스레드는 "동기화 된 메소드"또는 "객체"의 "동기화 된 코드 블록"으로의 액세스에서 차단됩니다. 아래는 "동기화 된 코드 블록"에 해당하는 데모 프로그램입니다.
클래스 myrunable emplements runnable {@override public void run () {synchronized (this) {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // sleep 100ms system.out.println (thread.currentthread (). getName () + "loop" + i); }} catch (InterruptedException IE) {}}}} public class demo1_1 {public static void main (String [] args) {runnable demo = new myRunable (); // 새 "runnable 객체"스레드 t1 = 새 스레드 (데모, "t1")를 만듭니다. // 새 "스레드 t1"을 만듭니다. t1은 런 가능한 개체 스레드 t2 = 새로운 스레드 (데모, "t2")를 기반으로합니다. // 새 "스레드 t2"를 만듭니다. t2는 런 가능한 개체 t1.start ()를 기반으로합니다. // 시작 "스레드 t1"t2.start (); // "스레드 t2"}} 시작 실행 결과 :
T1 루프 0T1 루프 1T1 루프 2T1 루프 3T1 루프 4T2 루프 0T2 루프 1T2 루프 2T2 루프 3T2 루프 4
결과는 run () 메소드에 "동기화 된 (이) 코드 블록"이 있고 T1과 T2는 runnable 객체를 기반으로 만든 스레드임을 보여줍니다. 이것은 우리가 이것을 동기화 (this)로 "데모 런닝 가능한 객체"로 간주 할 수 있음을 의미합니다. 따라서 스레드 T1과 T2는 "데모 객체의 동기 잠금"을 공유합니다. 따라서 한 스레드가 실행될 때 다른 스레드는 "실행 스레드"가 실행되기 전에 "데모 동기화 잠금"을 해제 할 때까지 기다려야합니다.
확인하면이 문제를 알아 냈습니다. 그런 다음 위의 코드를 수정 한 다음 결과가 어떻게되는지 확인하고 혼란 스러울 지 확인합니다. 수정 된 소스 코드는 다음과 같습니다.
클래스 신화는 스레드 {public mythread (문자열 이름) {super (name); } @override public void run () {synchronized (this) {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // sleep 100ms system.out.println (thread.currentthread (). getName () + "loop" + i); }} catch (InterruptedException IE) {}}}} public class demo1_2 {public static void main (String [] args) {스레드 t1 = new Mythread ( "T1"); // 새 "스레드 t1"스레드 t2 = new Mythread ( "t2")를 만듭니다. // 새 "스레드 t2"t1.start ()를 만듭니다. // 시작 "스레드 t1"t2.start (); // "스레드 t2"}} 시작 코드 설명 : Demo1_2와 Demo1_1을 비교하면 Demo1_2의 신화 클래스가 스레드에서 직접 상속되고 T1과 T2는 모두 신화 자식 스레드임을 발견했습니다.
다행히도 "run () demo1_2의 run () 메소드는 동기화 된 (this)라고도합니다.
그렇다면 Demo1_2의 실행 프로세스가 Demo1_1과 동일합니까? 실행 결과 :
T1 루프 0T2 루프 0T1 루프 1T2 루프 1T1 루프 2T2 루프 2T1 루프 3T2 루프 3T1 루프 4T2 루프 4
결과 설명 :
이 결과가 당신을 전혀 놀라게하지 않으면, 나는 당신이 동기화 된 것에 대해 더 깊이 이해하고 있다고 생각합니다. 그렇지 않으면 여기에서 분석을 계속 읽으십시오.
동기화 된 (이)에서는 "현재 클래스 객체", 즉 동기화 된 클래스 (this)가 위치한 클래스에 해당하는 현재 객체를 나타냅니다. 그 목적은 "현재 객체의 동기 잠금"을 얻는 것입니다.
DEMO1_2의 경우, 동기화 된 (이것은)에서는 신화 객체를 나타내고 T1과 T2는 두 가지 다른 신화 객체입니다. 따라서 T1과 T2가 동기화 된 (이)를 실행하면 다른 객체의 동기화 잠금을 얻습니다. Demo1_1 쌍의 경우, 이는 동기화 된 (이)의 Myrunable 객체를 나타냅니다. T1과 T2는 Myrunable 객체를 공유합니다. 따라서 한 스레드가 객체의 동기화 잠금을 획득하여 다른 스레드가 대기됩니다.
(2) 제 2 조 :
스레드가 "특정 객체"의 "동기화 된 메소드"또는 "동기화 된 코드 블록"에 액세스하면 다른 스레드는 여전히 "이 개체"의 비동기 코드 블록에 액세스 할 수 있습니다.
아래는 "동기화 된 코드 블록"에 해당하는 데모 프로그램입니다.
클래스 카운트 {// 동기화 된 동기화 블록을 포함하는 메소드 공개 void synmethod () {synchronized (this) {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // 100ms system.out.println (thread.currentThread (). getName () + "SynMethod loop" + i); }} catch (InterruptedException IE) {}}} // 비동기 메소드 public void nonsynmethod () {try {for (int i = 0; i <5; i ++) {strook.sleep (100); System.out.println (thread.currentthread (). getName () + "NonsynMethod loop" + i); }} catch (InterruptedException IE) {}}} public class demo2 {public static void main (String [] args) {최종 count = new count (); // 새 t1, t1은 "count 객체"스레드 t1 = new 스레드 (new runnable () {@override public void run () {count.synmethod ();}}, "t1")의 synmethod () 메소드를 호출합니다. // 새 t2를 생성하고, t2는 "count 객체"스레드 t2 = new 스레드의 nonsynmethod () 메소드를 호출합니다 (new runnable () {@override public void run () {count.nonsynmethod ();}}, "t2"); t1.start (); // 시작 t1 t2.start (); // 시작 t2}} 실행 결과 :
T1 Synmethod 루프 0T2 Nonsynmethod 루프 0T1 SynMethod 루프 1T2 Nonsynmethod 루프 1T1 Synmethod 루프 2T2 Nonsynmethod 루프 2T1 Symethod 루프 3T2 Nonsynmethod 루프 3T1 Symethod Loop 4T2 Nonsynmethod 루프 4
결과 설명 :
주 스레드에서 두 개의 새로운 자식 스레드 T1과 T2가 생성됩니다. T1은 동기화 블록을 포함하는 Count Object의 SynMethod () 메소드를 호출합니다. T2는 동기화 메소드가 아닌 Count Object의 NonsynMethod () 메소드를 호출합니다. T1이 실행될 때, 동기화 된 (this)는 "count synchronization lock"을 얻기 위해 호출되지만; T2가 "count"동기화 잠금을 사용하지 않기 때문에 T2가 차단되지 않습니다.
(3) 제 3 조 :
스레드가 "특정 객체"의 "동기화 된 메소드"또는 "동기화 된 코드 블록"에 액세스하면 다른 스레드는 다른 "동기화 된 메소드"또는 "객체"의 "동기화 된 코드 블록"에 대한 액세스가 차단됩니다.
또한 위의 예에서 동기화 된 (this)에서 nonsynmethod () 메소드 본문을 수정합니다. 수정 된 소스 코드는 다음과 같습니다.
클래스 카운트 {// 동기화 된 동기화 블록을 포함하는 메소드 공개 void synmethod () {synchronized (this) {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // 100ms system.out.println (thread.currentThread (). getName () + "SynMethod loop" + i); }} catch (InterruptedException IE) {}}} // 동기화 된 동기화 블록을 포함하는 메소드 공개 void nonsynmethod () {synchronized (this) {try {for (int i = 0; i <5; i ++) {strood.sleep (100); System.out.println (thread.currentthread (). getName () + "NonsynMethod loop" + i); }} catch (InterruptedException IE) {}}}} public class demo3 {public static void main (String [] args) {최종 count = new count (); // t1, t1을 create t1, t1은 "count 객체"스레드 t1 = new 스레드의 synmethod () 메소드를 호출합니다 (new Runnable () {@override public void run () {count.syncmethod ();}}, "t1"); // 새 t2를 생성하고, t2는 "count 객체"스레드 t2 = newsythod () 메소드를 호출합니다 (new runnable () {@override public void run () {count.nonsynmethod ();}}, "t2"); t1.start (); // 시작 t1 t2.start (); // 시작 t2}} 실행 결과 :
T1 Synmethod 루프 0T1 SynMethod 루프 1T1 Synmethod 루프 2T1 SynMethod 루프 3T1 SynMethod 루프 4T2 Nonsynmethod 루프 0T2 Nonsynmethod 루프 1T2 Nonsynmethod 루프 2T2 Nonsynmethod loop 3T2 Nonsynmedod 루프 4
결과 설명 :
주 스레드에서 두 개의 새로운 자식 스레드 T1과 T2가 생성됩니다. T1 및 T2는 모두 카운트 객체 (Count) 및 T1 및 T2 공유 카운트 인 동기화 (this)를 호출합니다. 따라서 T1이 실행될 때 T2가 차단되고 T1이 실행되면 T2가 실행되기 전에 "Count Object의 동기 잠금"을 해제하기 위해 T1이 실행됩니다.
3. 동기화 된 방법 및 동기화 된 코드 블록
"동기화 된 방법"은 동기화 된 수정 방법을 사용하는 반면 "동기화 된 코드 블록"은 동기화 된 수정 코드 블록을 사용합니다.
동기화 된 메소드 예제
public synchronized void foo1 () {system.out.println ( "synchronized method");} 동기화 된 코드 블록 공개 void foo2 () {synchronized (this) {system.out.println ( "synchronized method"); }} 동기화 된 코드 블록에서 이것은 현재 객체를 나타냅니다. 이것은 또한 OBJ로 대체되는 다른 객체로 대체 될 수 있으며, Foo2 ()는 동기화 될 때 OBJ의 동기화 잠금을 획득합니다 (OBJ).
동기화 된 코드 블록은 충돌 제한 액세스 영역을보다 정확하게 제어 할 수 있으며 때로는보다 효율적으로 수행 할 수 있습니다. 다음은 다음을 보여주는 예입니다.
// demo4.java의 소스 코드 public class demo4 {public synchronized void synmethod () {for (int i = 0; i <0000000; i ++); } public void synblock () {synchronized (this) {for (int i = 0; i <10000000; i ++); }} public static void main (String [] args) {demo4 demo = new demo4 (); 긴 시작, 차이; start = system.currenttimeMillis (); // 현재 시간을 가져옵니다 (millis) demo.syncmethod (); // "Synchronized Method"Diff = System.CurrentTimeMillis () - 시작; // "시차"system.out.println을 얻습니다 ( "syncmethod () :"+ diff); start = system.currenttimeMillis (); // 현재 시간을 가져옵니다 (millis) demo.syncblock (); // "Synchronized Method Block"Diff = System.CurrentTimeMillis () - 시작; // "시차"system.out.println을 얻습니다 ( "syncblock () :"+ diff); }} (한 번) 실행 결과 :
synmethod () : 11synblock () : 3
4. 인스턴스 잠금 및 글로벌 잠금
인스턴스 잠금-인스턴스 객체에서 잠금. 클래스가 싱글 톤이라면, 잠금 장치는 또한 글로벌 잠금의 개념을 가지고 있습니다.
(1) 동기화 된 키워드는 인스턴스 잠금에 해당합니다.
(2) 글로벌 잠금-자물쇠는 클래스를 대상으로합니다. 인스턴스의 객체 수에 관계없이 스레드는 잠금을 공유합니다.
글로벌 잠금은 정적 동기화 된 (또는이 클래스의 클래스 또는 클래스 로더 객체에 잠겨 있음)에 해당합니다.
"인스턴스 잠금"및 "글로벌 잠금"의 매우 생생한 예가 있습니다.
Pulbic Class Something {public synchronized void issynca () {} public synchronized void issyncb () {} public static synchronized void csynca () {} public static synchronized void csyncb () {}} 무언가에 두 가지 인스턴스 x와 y가 있다고 가정 해 봅시다. 다음 4 개의 표현 세트로 획득 한 자물쇠를 분석하십시오.
(1) X.issynca () 및 X.issyncb ()
(2) x.issynca () 및 y.issynca ()
(3) x.csynca () 및 y.csyncb ()
(4) x.issynca () 및 뭐든지 csynca ()
(1) 동시에 액세스 할 수 없습니다.
issynca () 및 issyncb ()는 동일한 객체 (객체 x)에 액세스하는 동기화 잠금이기 때문입니다!
// locktest1.java의 소스 코드 클래스 {public synchronized void asynca () {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // sleep 100ms system.out.println (thread.currentthread (). getName ()+": issynca"); }} catch (InterpruptedException IE) {}} public synchronized void void void istyncb () {try {for (int i = 0; i <5; i ++) {Thread.sleep (100); // 100ms system.out.println의 수면 (thread.currentThread (). getName ()+": issyncb"); }} catch (InterruptedException IE) {}}} public class locktest1 {something x = new Something (); y = 새로운 것 (); // (01) X.issynca ()와 x.issyncb () private void test1 () {// new t11, t11은 x.issynca () 스레드 t11 = 새 스레드 (new runnable () {@override public void run () {x.issynca ();}}, "t11"); // 새 t12를 생성하고, t12는 x.issyncb () 스레드 t12 = new 스레드 (new Runnable () {@override public void run () {x.issyncb ();}}, "t12")를 호출합니다. t11.start (); // 시작 t112.start (); // start t12} public static void main (String [] args) {locktest1 demo = new Locktest1 (); demo.test1 (); }} 실행 결과 :
T11 : ISSYNCAT11 : ISSYNCAT11 : ISSYNCAT11 : ISSYNCAT12 : ISSYNCBT12 : ISSYNCBT12 : ISSYNCBT12 : ISSYNCBT12 : ISSYNCBT12 : ISSYNCBT12 : ISSYNCBB : ISSYNCB
(2) 동시에 액세스 할 수 있습니다
동일한 객체의 동기화 잠금에 액세스하지 않기 때문에 x.issynca ()는 x의 동기화 잠금에 액세스하고 y.issynca ()는 y의 동기화 잠금에 액세스합니다.
// locktest2.java의 소스 코드 클래스 {public synchronized void void issynca () {try {for (int i = 0; i <5; i ++) {Thread.sleep (100); // sleep 100ms system.out.println (thread.currentthread (). getName ()+": issynca"); }} catch (InterpruptedException IE) {}} public synchronized void void void istyncb () {try {for (int i = 0; i <5; i ++) {Thread.sleep (100); // sleep 100ms system.out.println (thread.currentthread (). getName ()+": issyncb"); }} catch (InterruptedException IE) {}} 공개 정적 동기화 된 void csynca () {try {for (int i = 0; i <5; i ++) {strook.sleep (100); // sleep 100ms system.out.println (thread.currentthread (). getName ()+": csynca"); }} catch (InterruptedException IE) {}} 공개 정적 동기화 된 void csyncb () {try {for (int i = 0; i <5; i ++) {stride.sleep (100); // sleep 100ms system.out.println (thread.currentthread (). getName ()+": csyncb"); }} catch (InterpruptedException IE) {}}} public class locktest2 {something x = new Something (); y = 새로운 것 (); // (02) X.issynca ()와 y.issynca () private void test2 () {// 새 t21, t21은 x.issynca () 스레드 t21 = 새 스레드 (new Runnable () {@override public void Run () {x.issynca ();}}, "t21"; // 새 t22를 생성하고, t22는 x.issyncb () 스레드 t22 = new 스레드 (new Runnable () {@override public void run () {y.issynca ();}}, "t22")를 호출합니다. t21.start (); // 시작 t21 t22.start (); // start t22} public static void main (String [] args) {locktest2 demo = new Locktest2 (); demo.test2 (); }} 실행 결과 :
T21 : ISSYNCAT22 : ISSYNCAT21 : ISSYNCAT22 : ISSYNCAT21 : ISSYNCAT22 : ISSYNCAT21 : ISSYNCAT22 : ISSYNCAT21 : ISSYNCAT22 : ISSYNCAT22 : ISSYNCAT21 : ISSYNCAT22 : ISSYNCAT22 : ISSYNCAT22 : ISSYNCAT22 : ISSYNCAT22 : ISSYNCAT22 : ISSYNCAT22 : ISSYNCAT22 : ISSYNCAT22 : ISSYNCAT22 :
(3) 동시에 액세스 할 수 없습니다
csynca () 및 csyncb ()는 모두 정적 유형이기 때문에 x.csynca ()는 무언가와 동일하고 y.csyncb ()는 무언가와 동일합니다. issyncb ()는 동기화 잠금을 공유하며 동시에 요청할 수 없습니다.
// locktest3.java의 소스 코드 클래스 {public synchronized void void issynca () {try {for (int i = 0; i <5; i ++) {Thread.sleep (100); // sleep 100ms system.out.println (thread.currentthread (). getName ()+": issynca"); }} catch (InterpruptedException IE) {}} public synchronized void void void istyncb () {try {for (int i = 0; i <5; i ++) {Thread.sleep (100); // sleep 100ms system.out.println (thread.currentthread (). getName ()+": issyncb"); }} catch (InterruptedException IE) {}} 공개 정적 동기화 된 void csynca () {try {for (int i = 0; i <5; i ++) {strook.sleep (100); // sleep 100ms system.out.println (thread.currentthread (). getName ()+": csynca"); }} catch (InterruptedException IE) {}} 공개 정적 동기화 된 void csyncb () {try {for (int i = 0; i <5; i ++) {stride.sleep (100); // sleep 100ms system.out.println (thread.currentthread (). getName ()+": csyncb"); }} catch (InterpruptedException IE) {}}} public class locktest3 {something x = new Something (); y = 새로운 것 (); // y.csyncb () private void test3 ()와 (03) x.csynca ()를 비교합니다. // 새 t32를 생성하고, t32는 x.issyncb () 스레드 t32 = new 스레드 (new Runnable () {@override public void run () {y.csyncb ();}}, "t32")를 호출합니다. t31.start (); // 시작 t31 t32.start (); // start t32} public static void main (String [] args) {locktest3 demo = new Locktest3 (); demo.test3 (); }} 실행 결과 :
T31 : CSYNCAT31 : CSYNCAT31 : CSYNCAT31 : CSYNCAT31 : CSYNCAT32 : CSYNCBT32 : CSYNCBT32 : CSYNCBT32 : CSYNCBT32 : CSYNCBT32 : CSYNCBT32 : CSYNCBT32 : CSYNCBT32 : CSYNCBT32 : CSYNCBT32 : CSYNCBT32 : CSYNCBT32 : CSYNCBT32. CSYNCB
(4) 동시에 액세스 할 수 있습니다
issynca ()는 인스턴스 메소드이기 때문에 x.issynca ()는 객체 x의 잠금을 사용합니다. csynca ()는 정적 메소드이지만, csynca ()는 그것이 "클래스 잠금"이라는 것을 이해할 수 있습니다. 따라서 동시에 액세스 할 수 있습니다.
// locktest4.java의 소스 코드 클래스 {public synchronized void void issynca () {try {for (int i = 0; i <5; i ++) {Thread.sleep (100); // sleep 100ms system.out.println (thread.currentthread (). getName ()+": issynca"); }} catch (InterpruptedException IE) {}} public synchronized void void void istyncb () {try {for (int i = 0; i <5; i ++) {Thread.sleep (100); // sleep 100ms system.out.println (thread.currentthread (). getName ()+": issyncb"); }} catch (InterruptedException IE) {}} 공개 정적 동기화 된 void csynca () {try {for (int i = 0; i <5; i ++) {strook.sleep (100); // sleep 100ms system.out.println (thread.currentthread (). getName ()+": csynca"); }} catch (InterruptedException IE) {}} 공개 정적 동기화 된 void csyncb () {try {for (int i = 0; i <5; i ++) {stride.sleep (100); // 100ms system.out.println의 수면 (thread.currentThread (). getName ()+": csyncb"); }} catch (InterpruptedException IE) {}}} public class locktest4 {something x = new Something (); y = 새로운 것 (); // (04) x.issynca ()를 무언가와 비교합니다 .CSYNCA () private void test4 () {// 새 t41, t41은 x.issynca () 스레드 t41 = 새 스레드 (new runnable () {@override public void run () {x.issynca ();}}, "t41"; // 새 t42를 생성하고, t42는 x.issyncb () 스레드 t42 = new 스레드 (new Runnable () {@override public void run () {something.csynca ();}}, "t42"); t41.start (); // 시작 t41 t42.start (); // start t42} public static void main (String [] args) {locktest4 demo = new Locktest4 (); demo.test4 (); }} 실행 결과 :
T41 : ISSYNCAT42 : CSYNCAT41 : ISSYNCAT42 : CSYNCAT41 : ISSYNCAT42 : CSYNCAT41 : ISSYNCAT42 : CSYNCAT41 : ISSYNCAT42 : CSYNCAT41 : ISSYNCAT42 : CSYNCAT42 : CSYNCA.