Java에서 가장 기본적인 동기화 방법은 동기화된 키워드를 사용하여 메서드에 대한 동시 액세스를 제어하는 것입니다. 동기화된 키워드로 선언된 모든 메서드는 중요한 섹션입니다. Java에서는 동일한 객체의 하나의 중요한 섹션에만 동시에 액세스할 수 있습니다.
정적 메서드는 동작이 다릅니다. 동기화 키워드로 선언된 정적 메서드는 동시에 하나의 실행 스레드에서만 액세스할 수 있지만 다른 스레드는 이 개체의 비정적 동기화 메서드에 액세스할 수 있습니다. 두 스레드가 동시에 개체의 서로 다른 두 가지 동기화 메서드에 액세스할 수 있으므로 이에 대해 매우 주의해야 합니다. 즉, 그 중 하나는 정적 동기화 메서드이고 다른 하나는 비정적 동기화 메서드입니다. 두 방법 모두 동일한 데이터를 변경하면 데이터 불일치 오류가 발생합니다.
동기화 블록의 구문은 다음과 같습니다.
public void method() { synchronized(表达式) { } }
동기화 키워드에는 두 가지 용도가 있는데, 하나는 메소드 정의에만 사용되며 다른 하나는 동기화 블록일 뿐만 아니라. 동기화를 사용하여 개체 변수를 동기화할 수 있습니까? 또한 동기화를 사용하여 클래스의 정적 메서드와 비정적 메서드를 동기화할 수 있습니다.
첫 번째: 비정적 메소드의 동기화
관련 Java 구문을 통해 동기화된 키워드를 사용하여 메소드를 정의하면 정의된 정적 메소드와 비정적 메소드가 잠긴다는 것을 알 수 있습니다. 클래스의 static 메소드에서 synchroniezd 키워드를 사용하지만 이는 약간 이해하기 어렵습니다. 클래스에서 동기화된 비정적 메소드만 사용해야 합니다. 이는 동기화된 블록의 매개변수로 동기화된 블록에 전달됩니다.
public class Test { public void method1() { synchronized(this) { } } public synchronized void method2() { } } public class Test { public void method1() { synchronized(this) { } } public synchronized void method2() { } }
위 코드에서 method1 동기화된 블록을 사용하고, method2 메소드는 동기화된 키워드를 사용하여 메소드를 정의합니다. 동일한 테스트 인스턴스를 사용할 때 이 두 메소드 중 하나가 실행되는 동안 다른 메소드는 획득하지 못하기 때문에 차단됩니다. 동기화 잠금. 이것을 동기화 블록의 매개변수로 사용하는 것 외에도 Test.this를 동기화 블록의 매개변수로 사용하여 동일한 효과를 얻을 수도 있습니다.
내부 클래스에서 사용되는 동기화 블록에서는 내부 클래스만을 나타내며 외부 클래스(OuterClass)와는 아무런 관련이 없습니다. 그러나 내부 클래스의 비정적 메서드와 외부 클래스의 비정적 메서드도 동기화할 수 있습니다. 내부 클래스에 method3 메소드를 추가하면 Test의 두 메소드와 동기화할 수도 있습니다. 코드는 다음과 같습니다.
public class Test { class InnerClass { public void method3() { synchronized(Test.this){ } } } } public class Test { class InnerClass { public void method3() { synchronized(Test.this){ } } } }
위 InnerClass의 method3 메소드와 method1, method2 메소드 테스트는 동시에만 동기화할 수 있는 방법이 있습니다.
동기화된 블록이 올바르게 실행되었는지, 프로그램 오류로 인한 예외로 인해 동기화된 블록을 종료했는지 여부에 따라 현재 동기화된 블록이 보유하고 있던 동기화 잠금이 자동으로 해제되므로 동기화 잠금에 대해 걱정할 필요가 없습니다. 동기화된 블록을 사용할 때 문제가 발생합니다.
2. 정적 메소드 동기화
정적 메소드 호출 시 반드시 객체 인스턴스가 생성되는 것은 아니므로 이를 사용하여 정적 메소드를 동기화할 수는 없으나, 반드시 Class 객체를 사용하여 동기화해야 합니다. 정적 방법. 코드는 다음과 같습니다.
public class Test{ pubic static void method1(){ synchronized(Test.class){ } } public static synchronized void method2(){ } } public class Test{ pubic static void method1(){ synchronized(Test.class){ } } public static synchronized void method2(){ } }
정적 메소드를 동기화할 때 클래스의 정적 필드 클래스를 사용하여 클래스 객체를 가져올 수 있습니다. 위 예에서 method1 및 method2 메소드에는 하나의 메소드만 있습니다. 클래스 필드를 사용하는 것 외에도, 인스턴스의 getClass() 메소드를 통해 클래스 객체를 얻을 수도 있습니다.
public class Test{ public static Test test; public Test(){ test=this; } public static void method1(){ synchronized(test.getClass()){ } } } public class Test{ public static Test test; public Test(){ test=this; } public static void method1(){ synchronized(test.getClass()){ } } }
위 코드에서는 공용 정적 객체를 통해 Test 인스턴스를 얻고 인스턴스의 getClass 메소드를 전달합니다. getClass 메소드는 클래스 객체를 얻습니다(클래스의 모든 인스턴스는 getClass 메소드를 통해 동일한 Class 객체를 얻습니다). 클래스를 통해 다양한 클래스의 정적 메서드를 동기화할 수도 있습니다.
public class Test1{ public static void method1(){ synchronized(Test.class){ } } } public class Test1{ public static void method1(){ synchronized(Test.class){ } } }
참고: 동기화된 블록을 사용하여 메서드를 동기화하는 경우 이를 통해 비정적 메서드를 동기화할 수 있습니다. 동기화하려면 클래스 객체를 사용해야 하지만 비정적 메서드도 클래스를 사용하여 정적 메서드를 동기화할 수 있습니다. 그러나 이는 비정적 메서드를 동기화하기 위해 정적 메서드에서 사용할 수 없습니다. 동기화된 블록을 사용할 때 이 점에 유의해야 합니다.
참고
동기화 키워드는 애플리케이션의 성능을 저하시키므로 공유 데이터를 수정해야 하는 메서드에 대한 동시 시나리오에서만 사용할 수 있습니다. 여러 스레드가 동일한 동기화 메서드에 액세스하는 경우 하나의 스레드만 해당 메서드에 액세스할 수 있으며 다른 스레드는 대기합니다. 메서드 선언에서 동기화 키워드를 사용하지 않으면 모든 스레드가 동시에 메서드를 실행할 수 있으므로 총 실행 시간이 줄어듭니다. 둘 이상의 스레드에서 메서드를 호출하지 않는 것으로 알려진 경우에는 동기화 키워드를 사용하여 메서드를 선언할 필요가 없습니다.
동기화로 선언된 메서드는 재귀적으로 호출할 수 있습니다. 스레드가 개체의 동기화된 메서드에 액세스하면 이 메서드에 다시 액세스하지 않고도 실행 중인 메서드를 포함하여 개체의 다른 동기화된 메서드를 호출할 수도 있습니다.
我们可以通过synchronized关键字来保护代码块(而不是整个方法)的访问。应该这样利用synchronized关键字:方法的其余部分保持在synchronized代码块之外,以获取更好的性能。临界区(即同一时间只能被一个线程访问的代码块)的访问应该尽可能的短。例如在获取一幢楼人数的操作中,我们只使用synchronized关键字来保护对人数更新的指令,并让其他操作不使用共享数据。当这样使用synchronized关键字时,必须把对象引用作为传入参数。同一时间只有一个线程被允许访问这个synchronized代码。通常来说,我们使用this关键字来引用正在执行的方法所属的对象:
synchronized(this){ //Java code }
更多Java中synchronized关键字修饰方法同步的用法详解相关文章请关注PHP中文网!