>  기사  >  Java  >  Java가 다중 스레드 동기화를 달성하기 위해 동기화를 사용하는 방법

Java가 다중 스레드 동기화를 달성하기 위해 동기화를 사용하는 방법

PHPz
PHPz앞으로
2023-04-30 16:19:071032검색

동기화를 사용하는 이유

1. 시스템의 클래스에 접근하려면 멀티스레드를 사용해야 합니다.

2. 클래스에 클래스 변수가 있거나, 클래스 메서드에서 공용 리소스(예: 외부 파일)에 접근합니다. . 읽기 및 쓰기).

동기화 잠금으로 잠긴 콘텐츠는 무엇인가요?

메서드나 변수 앞에 동기화를 추가하면 클래스 개체가 잠깁니다. 각 객체에는 연관된 잠금이 하나만 있습니다.

다음 예는 다양한 상황에서의 동기화 효과를 나열합니다

1. 메소드에 동기화가 추가됩니다(동기화 메소드, 잠금 클래스 인스턴스)

Java 코드

public class Demo1 {             public synchronized void m1(){             //...............         }             public void m2(){             //............                 synchronized(this){                 //.........             }                 //........         }     }

이 두 가지 쓰기 메소드의 효과는 마찬가지로 잠긴 것은 모두 클래스 인스턴스 객체입니다. 클래스 인스턴스 객체가 있는 경우(demo = new Demo1()), 두 개의 스레드(thread1, thread2)가 있고 둘 다 데모 객체를 호출하는 경우 동시에 thread1이 데모.m1()을 호출하면 thread2는 데모.m1() 및 데모.m2()에서는 해당 시간 동안 액세스할 수 없습니다. 스레드1이 데모 개체의 잠금을 사용하기 때문에 다른 스레드에 할당할 수 없습니다. Demo2 .m1() 호출은 서로 다른 Demo1 클래스 객체 인스턴스를 호출하기 때문에 동시에 수행될 수 있습니다.

2.Synchronized가 변수에 추가됩니다. (동기화 블록, 잠긴 클래스 인스턴스)

Java 코드

public class Demo2 {         Object a = new Object();         Object b = new Object();             public void m1(){             //............                 synchronized(a){                 //.........             }                 //........         }             public void m2(){             //............                 synchronized(b){                 //.........             }                 //........         }     }
이 경우 코드 블록 잠금이 구현되며 잠긴 개체는 변수 a 또는 b입니다. , a 및 b는 모두 비정적입니다) 클래스 인스턴스 객체가 있는 경우: 데모 = new Demo2(), 두 개의 스레드(thread1, thread2)가 있으며 둘 다 데모 객체를 호출하고 동시에 thread1이 호출하는 경우 데모.m1()이면 thread2는 이 시간 내에 데모.m2()에 액세스할 수 있지만 a는 thread1에 의해 잠겨 있으므로 데모.m1()의 동기화 블록에 액세스할 수 없습니다.

3. 동기화된 잠금 클래스 변수, 즉 정적 변수(속성일 수도 있고 메서드일 수도 있음)(클래스 개체 잠금)

Java 코드

public class Demo3 {         static Object o = new Object();             public static synchronized void m1() {             //....         }             public static void m2() {             //...             synchronized (Demo3.class) {                 //.....             }             //.....         }             public static void m3() {             //..........             try {                 synchronized (Class.forName("Demo3")) {                   //............                 }             } catch (ClassNotFoundException ex) {             }             //.............         }             public static void m4() {             //............            synchronized(o){              //........            }             //..........         }     }
위의 네 가지 메서드에서 얻는 효과는 동일합니다. 잠긴 객체는 모두 클래스 인스턴스 객체가 아닌 Demo3 클래스입니다. 즉, 멀티 스레드에서 공유 리소스는 클래스 객체가 아닌 클래스에 속합니다. 이 경우 thread1이 이 네 가지 메서드 중 하나에 액세스하면 다른 스레드는 이 네 가지 메서드에 동시에 액세스할 수 없습니다.

4. 클래스 메소드는 여러 스레드에 공통된 리소스에 액세스하며 리소스는 가변적입니다. 이 경우에도 동기화가 필요합니다

Java 코드

public class Demo4 {         static String path = "file path";             public void readConfiFile() {             synchronized (path) {                // 读取该path指定的文件。             }             }             public void writeConfiFile() {             synchronized (path) {                 //写信息到该path指定的文件。             }         }     }
이 경우에는 잠가야 합니다. 클래스 변수는 잠길 수 없습니다. 클래스 인스턴스 객체에 잠겨 있습니다. 이는 클래스 인스턴스 객체 리소스 공유가 아닌 변수의 클래스 리소스 공유 유형이기 때문입니다.

스레드에는 성공과 실패의 방식이 있습니다. 잘 사용하면 성능이 향상되지만 잘못 사용하면 시스템에 끝없는 문제를 야기합니다.

PS: 스레드 동기화에는 시스템 오버헤드가 많이 필요하므로 사용 시 꼭 필요하지 않은 경우 동기화 기능을 사용하지 않는 것이 좋습니다.

위 내용은 Java가 다중 스레드 동기화를 달성하기 위해 동기화를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제