CodeGym /Java Blog /무작위의 /스레드 동기화. 동기화된 연산자
John Squirrels
레벨 41
San Francisco

스레드 동기화. 동기화된 연산자

무작위의 그룹에 게시되었습니다
안녕! 오늘 우리는 계속해서 다중 스레드 프로그래밍의 기능을 고려하고 스레드 동기화에 대해 이야기할 것입니다. 스레드 동기화.  동기화 연산자 - 1

Java에서 동기화란 무엇입니까?

프로그래밍 영역 밖에서는 두 개의 장치 또는 프로그램이 함께 작동하도록 허용하는 배열을 의미합니다. 예를 들어 스마트폰과 컴퓨터를 Google 계정과 동기화할 수 있고, 웹사이트 계정을 소셜 네트워크 계정과 동기화하여 로그인할 수 있습니다. 스레드 동기화는 유사한 의미를 가집니다. 서로. 이전 학습에서는 스레드가 서로 별도로 작동했습니다. 하나는 계산을 수행했고, 두 번째는 잠을 잤고, 세 번째는 콘솔에 무언가를 표시했지만 상호 작용하지 않았습니다. 실제 프로그램에서는 이러한 상황이 거의 발생하지 않습니다. 여러 스레드가 동일한 데이터 세트를 적극적으로 사용하고 수정할 수 있습니다. 이로 인해 문제가 발생합니다. 예를 들어 텍스트 파일이나 콘솔과 같은 동일한 위치에 텍스트를 쓰는 여러 스레드를 상상해 보십시오. 이 경우 파일 또는 콘솔은 공유 리소스가 됩니다. 스레드는 서로의 존재를 알지 못하므로 스레드 스케줄러가 할당한 시간 내에 가능한 모든 것을 작성합니다. 최근 수업에서 우리는 이것이 어디로 이어지는지에 대한 예를 보았습니다. 지금 기억해 봅시다. 스레드 동기화.  동기화 연산자 - 2그 이유는 스레드가 서로 작업을 조정하지 않고 공유 리소스(콘솔)와 함께 작업하기 때문입니다. 스레드 스케줄러가 Thread-1에 시간을 할당하면 즉시 모든 것을 콘솔에 기록합니다. 다른 스레드가 이미 작성했거나 아직 작성하지 않은 것은 중요하지 않습니다. 보시다시피 결과는 우울합니다. 그래서 멀티스레드 프로그래밍에 뮤텍스(상호 배제) 라는 특별한 개념을 도입했습니다. 뮤텍스의 목적특정 시간에 하나의 스레드만 개체에 액세스할 수 있도록 메커니즘을 제공하는 것입니다. Thread-1이 개체 A의 뮤텍스를 획득하면 다른 스레드는 개체에 액세스하고 수정할 수 없습니다. 다른 스레드는 개체 A의 뮤텍스가 해제될 때까지 기다려야 합니다. 다음은 삶의 예입니다. 귀하와 다른 10명의 낯선 사람들이 운동에 참여하고 있다고 상상해 보십시오. 번갈아 가며 아이디어를 표현하고 무언가를 논의해야 합니다. 하지만 서로 처음 보는 것이기 때문에 끊임없이 서로를 방해하고 화를 내지 않기 위해 '말하는 공'을 사용합니다. 공을 가진 사람만 말을 할 수 있습니다. 이렇게 하면 훌륭하고 유익한 토론을 끝낼 수 있습니다. 기본적으로 공은 뮤텍스입니다. 개체의 뮤텍스가 한 스레드의 손에 있는 경우 다른 스레드는 개체를 사용할 수 없습니다.Object이는 Java의 모든 개체에 하나씩 있음을 의미합니다.

동기화 연산자 작동 방식

새 키워드인 synchronized 에 대해 알아봅시다 . 특정 코드 블록을 표시하는 데 사용됩니다. 코드 블록에 synchronized키워드가 표시된 경우 해당 블록은 한 번에 하나의 스레드에서만 실행할 수 있습니다. 동기화는 다양한 방법으로 구현할 수 있습니다. 예를 들어 전체 메서드를 동기화하도록 선언하면 다음과 같습니다.

public synchronized void doSomething() {

   // ...Method logic
}
또는 일부 개체를 사용하여 동기화가 수행되는 코드 블록을 작성합니다.

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...Some logic available simultaneously to all threads

       synchronized (obj) {

           // Logic available to just one thread at a time
       }
   }
}
의미는 간단합니다. 하나의 스레드가 키워드로 표시된 코드 블록 내부로 들어가면 synchronized즉시 개체의 뮤텍스를 캡처하고 동일한 블록이나 메서드에 들어가려는 다른 모든 스레드는 이전 스레드가 작업을 완료하고 모니터를 해제할 때까지 강제로 대기합니다. 스레드 동기화.  동기화된 연산자 - 3그런데! 과정 중에 이미 의 예를 보았지만 synchronized다르게 보였습니다.

public void swap()
{
   synchronized (this)
   {
       // ...Method logic
   }
}
주제는 당신에게 새로운 것입니다. 그리고 물론 구문에 혼동이 있을 것입니다. 따라서 나중에 다른 작성 방법으로 혼동되지 않도록 즉시 암기하십시오. 이 두 가지 작성 방법은 같은 의미입니다.

public void swap() {

   synchronized (this)
   {
       // ...Method logic
   }
}


public synchronized void swap() {

   }
}
첫 번째 경우 메서드를 입력하는 즉시 동기화된 코드 블록을 만듭니다. this객체, 즉 현재 객체 에 의해 동기화됩니다 . 두 번째 예에서는 synchronized키워드를 전체 메서드에 적용합니다. 이렇게 하면 동기화에 사용되는 개체를 명시적으로 표시할 필요가 없습니다. 전체 메서드가 키워드로 표시되기 때문에 메서드는 클래스의 모든 인스턴스에 대해 자동으로 동기화됩니다. 우리는 어떤 방법이 더 나은지에 대한 논의에 뛰어들지 않을 것입니다. 지금은 가장 마음에 드는 방법을 선택하세요 :) 가장 중요한 점은 모든 논리가 한 번에 하나의 스레드에 의해 실행될 때만 동기화된 메서드를 선언할 수 있다는 것입니다. 예를 들어 다음 메서드를 동기화하는 것은 실수입니다 doSomething().

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...Some logic available simultaneously to all threads

       synchronized (obj) {

           // Logic available to just one thread at a time
       }
   }
}
보시다시피 메서드의 일부에는 동기화가 필요하지 않은 논리가 포함되어 있습니다. 이 코드는 동시에 여러 스레드에서 실행할 수 있으며 모든 중요한 위치는 별도의 synchronized블록에 따로 설정됩니다. 그리고 하나 더. 이름 교환을 사용하여 수업에서 사용한 예를 자세히 살펴보겠습니다.

public void swap()
{
   synchronized (this)
   {
       // ...Method logic
   }
}
참고: 동기화는 를 사용하여 수행됩니다this. 즉, 특정MyClass개체를 사용하는 것입니다. Thread-12개의 스레드( 및Thread-2)와 하나의 객체만있다고 가정합니다MyClass myClass. 이 경우Thread-1호출하면myClass.swap()개체의 뮤텍스가 사용 중이며 호출을 시도하면뮤텍스가 해제되기를 기다리는 동안myClass.swap()메서드가2개의 스레드와 2개의 개체(및Thread-2가 있는 경우스레드는 서로 다른 개체에서 동기화된 메서드를 쉽게 동시에 실행할 수 있습니다. 첫 번째 스레드는 다음을 실행합니다. MyClassmyClass1myClass2

myClass1.swap();
두 번째는 다음을 실행합니다.

myClass2.swap();
이 경우 특정 개체를 사용하여 동기화가 수행되므로 메서드 synchronized내부의 키워드는 swap()프로그램 작업에 영향을 미치지 않습니다. 후자의 경우 2개의 개체가 있습니다. 따라서 스레드는 서로에게 문제를 일으키지 않습니다. 결국, 두 개체에는 두 개의 서로 다른 뮤텍스가 있으며 하나를 획득하는 것은 다른 하나를 획득하는 것과는 별개입니다 .

정적 메서드에서 동기화의 특수 기능

그러나 정적 메서드를 동기화해야 하는 경우에는 어떻게 해야 합니까 ?

class MyClass {
   private static String name1 = "Ally";
   private static String name2 = "Lena";

   public static synchronized void swap() {
       String s = name1;
       name1 = name2;
       name2 = s;
   }

}
여기서 뮤텍스가 어떤 역할을 하는지는 명확하지 않습니다. 결국 우리는 이미 각 개체에 뮤텍스가 있다고 결정했습니다. 그러나 문제는 메서드를 호출하는 데 개체가 필요하지 않다는 것입니다 MyClass.swap(). 메서드는 정적입니다! 다음은 무엇입니까? :/ 실제로 여기에는 문제가 없습니다. Java 작성자가 모든 것을 처리했습니다 :) 중요한 동시 논리를 포함하는 메서드가 정적이면 클래스 수준에서 동기화가 수행됩니다. 더 명확하게 하기 위해 위의 코드를 다음과 같이 다시 작성할 수 있습니다.

class MyClass {
   private static String name1 = "Ally";
   private static String name2 = "Lena";

   public static void swap() {

       synchronized (MyClass.class) {
           String s = name1;
           name1 = name2;
           name2 = s;
       }
   }

}
원칙적으로는 다음과 같이 스스로 생각할 수 있습니다. 객체가 없기 때문에 동기화 메커니즘이 어떻게든 클래스 자체에 적용되어야 합니다. 이것이 바로 그 방법입니다. 클래스를 사용하여 동기화할 수 있습니다.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION