[java] ‘동기화’란 무엇입니까?

synchronized키워드 의 사용법과 중요성에 대해 몇 가지 질문이 있습니다 .

  • synchronized키워드 의 의미는 무엇입니까 ?
  • 방법은 언제해야 synchronized합니까?
  • 프로그래밍 방식 및 논리적 의미는 무엇입니까?


답변

synchronized키워드는 읽기와 같은 변수, 객체, 자원에 쓰는 다른 스레드에 대한 모든 것입니다. 이것은 Java에서 사소한 주제는 아니지만 Sun의 인용문입니다.

synchronized 메소드는 스레드 간섭 및 메모리 일관성 오류를 방지하기위한 간단한 전략을 가능하게합니다. 오브젝트가 둘 이상의 스레드에 표시되면 해당 오브젝트 변수에 대한 모든 읽기 또는 쓰기는 동기화 된 메소드를 통해 수행됩니다.

매우 작은 요컨대 , 같은 ‘자원’에 읽고 쓰는 두 개의 스레드가있는 경우 (예 : 변수) foo, 이러한 스레드가 원자 방식으로 변수에 액세스해야합니다. synchronized키워드가 없으면 스레드 1이 변경 스레드 2를 보지 못 foo하거나 더 이상 절반 만 변경 될 수 있습니다. 이것은 논리적으로 기대하는 것이 아닙니다.

다시 말하지만, 이것은 Java에서 사소한 주제입니다. 자세한 내용을 보려면 SO 및 인터 웹에 대한 다음 주제를 탐색하십시오.

“Brian Goetz” 라는 이름 이 뇌의 “동시성” 이라는 용어와 영구적으로 연관 될 때까지 이러한 주제를 계속 탐색하십시오 .


답변

글쎄, 우리는 충분한 이론적 설명을 가지고 있다고 생각 하므로이 코드를 고려하십시오.

public class SOP {
    public static void print(String s) {
        System.out.println(s+"\n");
    }
}

public class TestThread extends Thread {
    String name;
    TheDemo theDemo;
    public TestThread(String name,TheDemo theDemo) {
        this.theDemo = theDemo;
        this.name = name;
        start();
    }
    @Override
    public void run() {
        theDemo.test(name);
    }
}

public class TheDemo {
    public synchronized void test(String name) {
        for(int i=0;i<10;i++) {
            SOP.print(name + " :: "+i);
            try{
                Thread.sleep(500);
            } catch (Exception e) {
                SOP.print(e.getMessage());
            }
        }
    }
    public static void main(String[] args) {
        TheDemo theDemo = new TheDemo();
        new TestThread("THREAD 1",theDemo);
        new TestThread("THREAD 2",theDemo);
        new TestThread("THREAD 3",theDemo);
    }
}

참고 : synchronized이전 스레드의 실행이 완료되지 않는 한 다음 스레드의 메소드 test () 호출을 차단합니다. 스레드는 한 번에 하나씩이 메소드에 액세스 할 수 있습니다. synchronized모든 스레드가 없으면 이 메소드에 동시에 액세스 할 수 있습니다.

스레드가 오브젝트의 동기화 된 메소드 ‘test'(여기서 오브젝트는 ‘TheDemo’클래스의 인스턴스 임)를 호출 할 때 해당 오브젝트의 잠금을 획득하면 새 스레드는 이전 스레드와 동일한 오브젝트의 동기화 된 메소드를 호출 할 수 없습니다 잠금을 획득 한 잠금은 해제되지 않습니다.

클래스의 정적 동기화 메소드가 호출 될 때도 비슷한 일이 발생합니다. 스레드는 클래스와 연관된 잠금을 획득합니다 (이 경우 해당 클래스 인스턴스의 정적이 아닌 동기화 된 메소드는 해당 오브젝트 레벨 잠금이 여전히 사용 가능하므로 스레드에 의해 호출 될 수 있음). 클래스 레벨 잠금이 현재 잠금을 보유한 스레드에 의해 해제되지 않는 한 다른 스레드는 클래스의 정적 동기화 메소드를 호출 할 수 없습니다.

동기화 된 출력

THREAD 1 :: 0
THREAD 1 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 1 :: 4
THREAD 1 :: 5
THREAD 1 :: 6
THREAD 1 :: 7
THREAD 1 :: 8
THREAD 1 :: 9
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 3 :: 4
THREAD 3 :: 5
THREAD 3 :: 6
THREAD 3 :: 7
THREAD 3 :: 8
THREAD 3 :: 9
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 2 :: 4
THREAD 2 :: 5
THREAD 2 :: 6
THREAD 2 :: 7
THREAD 2 :: 8
THREAD 2 :: 9

동기화되지 않은 출력

THREAD 1 :: 0
THREAD 2 :: 0
THREAD 3 :: 0
THREAD 1 :: 1
THREAD 2 :: 1
THREAD 3 :: 1
THREAD 1 :: 2
THREAD 2 :: 2
THREAD 3 :: 2
THREAD 1 :: 3
THREAD 2 :: 3
THREAD 3 :: 3
THREAD 1 :: 4
THREAD 2 :: 4
THREAD 3 :: 4
THREAD 1 :: 5
THREAD 2 :: 5
THREAD 3 :: 5
THREAD 1 :: 6
THREAD 2 :: 6
THREAD 3 :: 6
THREAD 1 :: 7
THREAD 2 :: 7
THREAD 3 :: 7
THREAD 1 :: 8
THREAD 2 :: 8
THREAD 3 :: 8
THREAD 1 :: 9
THREAD 2 :: 9
THREAD 3 :: 9


답변

synchronized키워드는 여러 스레드에 의해 코드 또는 객체의 블록에 대한 동시 액세스를 방지합니다. 모든 방법이 Hashtable있다 synchronized그래서 한 번에 하나의 스레드 만에 그 중 하나를 실행할 수 있습니다.

synchronized와 같은 구문 이외의 구문을 사용 HashMap하는 경우 일관성 오류를 방지하기 위해 코드에 스레드 안전 기능을 빌드해야합니다.


답변

synchronized다중 스레드 환경에서, synchronized메소드 / 블록을 갖는 객체 는 두 스레드가 synchronized동시에 코드 의 메소드 / 블록 에 액세스하는 것을 허용하지 않습니다 . 즉, 한 스레드는 읽을 수없고 다른 스레드는이를 업데이트 할 수 없습니다.

두 번째 스레드는 대신 첫 번째 스레드가 실행을 완료 할 때까지 기다립니다. 오버 헤드는 속도이지만 이점은 데이터의 일관성을 보장합니다.

응용 프로그램이 단일 스레드 인 경우 synchronized블록은 이점을 제공하지 않습니다.


답변

synchronized키워드 방식을 입력 할 때 (이 정적 메소드가 아니면, 지정된 객체 인스턴스에 대한) 단 하나 개의 스레드가 동시에 상기 방법을 실행할 수 있도록하는 것이, 로크를 획득하기 위해 스레드를 야기한다.

이것을 클래스 안전 스레드 만들기라고 부르지 만 이것이 완곡주의라고 말할 것입니다. 동기화가 Vector의 내부 상태가 손상되는 것을 방지하는 것은 사실이지만 일반적으로 Vector 사용자에게 큰 도움이되지는 않습니다.

이걸 고려하세요:

 if (vector.isEmpty()){
     vector.add(data);
 }

관련된 메소드는 동기화되어 있지만 개별적으로 잠금 및 잠금 해제되어 있기 때문에 불행하게도 시간이 걸리는 두 개의 스레드가 두 개의 요소로 벡터를 만들 수 있습니다.

따라서 실제로 응용 프로그램 코드에서도 동기화해야합니다.

메소드 레벨 동기화는 a) 필요하지 않을 때 비싸고 b) 동기화가 필요할 때 불충분하기 때문에 동기화되지 않은 대체 (Vector의 경우 ArrayList)가 있습니다.

최근에는 멀티 스레딩 문제를 처리하는 많은 영리한 유틸리티와 함께 ​​동시성 패키지가 릴리스되었습니다.


답변

개요

Java에서 동기화 된 키워드는 스레드 안전성과 관련이 있습니다. 즉, 여러 스레드가 동일한 변수를 읽거나 쓸 때입니다.
이것은 같은 변수에 직접 액세스하거나 같은 변수에 액세스하는 다른 클래스를 사용하는 클래스를 사용하여 간접적으로 발생할 수 있습니다.

synchronized 키워드는 여러 스레드가 동일한 변수에 안전하게 액세스 할 수있는 코드 블록을 정의하는 데 사용됩니다.

더 깊은

구문 측면에서 synchronized키워드는 Object매개 변수 ( lock 객체 라고 함)를 취한 다음 뒤에을 붙 { block of code }입니다.

  • 실행시이 키워드가 발생하면 현재 스레드는 잠금 개체 를 “잠금 / 취득 / 소유”(선택)하고 잠금 이 획득 된 후 관련 코드 블록을 실행 하려고합니다 .

  • 동기화 된 코드 블록 내의 변수에 대한 모든 쓰기는 동일한 잠금 객체를 사용하여 동기화 된 코드 블록 내의 코드를 유사하게 실행하는 다른 모든 스레드에서 볼 수 있도록 보장됩니다 .

  • 한 번에 하나의 스레드 만 잠금을 보유 할 수 있으며이 시간 동안 동일한 잠금 오브젝트 를 확보하려는 다른 모든 스레드 는 대기합니다 (실행 일시 중지). 실행이 동기화 된 코드 블록을 종료하면 잠금이 해제됩니다.

동기화 된 방법 :

추가 synchronized메소드 정의하면 키워드와 동기 코드 블록에서 전체 랩핑 방법 본체 같다 로크 대상의 존재 this (예 방법의 경우)ClassInQuestion.getClass() (클래스 메소드) .

-인스턴스 메소드는 static키워드 가없는 메소드입니다 .
-클래스 메소드는 static키워드 가있는 메소드입니다 .

인위적인

동기화가 없으면 읽기 및 쓰기 순서가 보장되지 않아 변수에 가비지가 남을 수 있습니다.
예를 들어 변수는 한 스레드가 쓴 비트의 절반과 다른 스레드가 쓴 비트의 절반으로 끝나서 스레드 중 어느 것도 쓰지 않았지만 두 가지가 혼잡 한 상태로 변수를 남길 수 있습니다.

하드웨어가 변수의 값을 캐시 할 수 있고 읽기 스레드가 작성된 값 대신 캐시 된 값을 볼 수 있기 때문에 다른 스레드가 읽기 전에 (벽 시계 시간) 스레드에서 쓰기 조작을 완료하는 것만으로는 충분하지 않습니다. 그것.

결론

따라서 Java의 경우 스레딩 오류가 발생하지 않도록 Java 메모리 모델을 따라야합니다.
다시 말해 : 후드 아래에서 동기화, 원 자성 작업 또는 클래스를 사용하는 클래스를 사용하십시오.

출처

http://docs.oracle.com/javase/specs/jls/se8/html/index.html
Java® 언어 사양, 2015-02-13


답변

축구장에서 볼 수 있듯이 일종의 개찰구라고 생각하십시오. 들어오고 자하는 사람들의 평행 증기가 있지만 개찰구에서 그들은 ‘동기화’됩니다. 한 번에 한 사람 만 통과 할 수 있습니다. 극복하기를 원하는 모든 사람들이 할 것이지만, 통과 할 때까지 기다려야 할 수도 있습니다.