Java의 동기화
다중 스레드 프로그램에서는 여러 스레드가 동일한 리소스에 액세스하려고 시도하여 최종적으로 오류가 있거나 예상치 못한 결과를 생성하는 상황이 종종 발생할 수 있습니다.
Java 동기화를 사용하는 이유는 무엇입니까?
Java 동기화는 특정 시점에 하나의 스레드만 리소스에 액세스할 수 있도록 동기화 방법을 사용하는 데 사용됩니다.
Java 동기화 블록
Java는 동기화된 블록을 사용하여 스레드를 생성하고 해당 작업을 동기화하는 방법을 제공합니다.
Java의 동기화된 블록은 일부 객체에서 동기화됩니다. 모든 동기화된 블록은 동일한 개체에서 동기화되며 한 번에 하나의 스레드만 내부에서 실행될 수 있습니다. 동기화된 블록에 들어가려는 다른 모든 스레드는 동기화된 블록 내부의 스레드가 블록을 종료할 때까지 차단됩니다.
메모: Java의 동기화된 블록은 동기화된 키워드로 표시됩니다.
동기화된 블록의 일반적인 형태
// Only one thread can execute at a time. // sync_object is a reference to an object // whose lock associates with the monitor . // The code is said to be synchronized on // the monitor object synchronized(sync_object) { // Access shared variables and other // shared resources } 이 동기화는 모니터 또는 잠금이라는 개념을 사용하여 Java에서 구현됩니다. 주어진 시간에 단 하나의 스레드만이 모니터를 소유할 수 있습니다. 스레드가 잠금을 획득하면 모니터에 진입했다고 합니다. 잠긴 모니터에 들어가려고 시도하는 다른 모든 스레드는 첫 번째 스레드가 모니터를 종료할 때까지 일시 중단됩니다.
동기화 유형
Java에는 아래에 언급된 두 가지 동기화가 있습니다.
- 프로세스 동기화
- 스레드 동기화
1. Java의 프로세스 동기화
프로세스 동기화는 여러 프로세스의 실행을 조정하는 데 사용되는 기술입니다. 이는 공유 리소스가 안전하고 질서있게 유지되도록 보장합니다.
2. Java의 스레드 동기화
스레드 동기화는 다중 스레드 프로그램에서 스레드 실행을 조정하고 순서를 지정하는 데 사용됩니다. 스레드 동기화에는 아래에 두 가지 유형이 언급되어 있습니다.
- 상호 배타적
- 협력(Java의 스레드 간 통신)
상호 배타적
Mutual Exclusive는 데이터를 공유하는 동안 스레드가 서로 간섭하지 않도록 도와줍니다. 아래에 언급된 상호 배타적 유형에는 세 가지가 있습니다.
- 동기화된 방법.
- 동기화된 블록.
- 정적 동기화.
동기화의 예
다음은 Java 동기화 구현입니다.
자바
// A Java program to demonstrate working of> // synchronized.> import> java.io.*;> import> java.util.*;> // A Class used to send a message> class> Sender {> > public> void> send(String msg)> > {> > System.out.println(> 'Sending '> + msg);> > try> {> > Thread.sleep(> 1000> );> > }> > catch> (Exception e) {> > System.out.println(> 'Thread interrupted.'> );> > }> > System.out.println(> '
'> + msg +> 'Sent'> );> > }> }> // Class for send a message using Threads> class> ThreadedSend> extends> Thread {> > private> String msg;> > Sender sender;> > // Receives a message object and a string> > // message to be sent> > ThreadedSend(String m, Sender obj)> > {> > msg = m;> > sender = obj;> > }> > public> void> run()> > {> > // Only one thread can send a message> > // at a time.> > synchronized> (sender)> > {> > // synchronizing the send object> > sender.send(msg);> > }> > }> }> // Driver class> class> SyncDemo {> > public> static> void> main(String args[])> > {> > Sender send => new> Sender();> > ThreadedSend S1 => new> ThreadedSend(> ' Hi '> , send);> > ThreadedSend S2 => new> ThreadedSend(> ' Bye '> , send);> > // Start two threads of ThreadedSend type> > S1.start();> > S2.start();> > // wait for threads to end> > try> {> > S1.join();> > S2.join();> > }> > catch> (Exception e) {> > System.out.println(> 'Interrupted'> );> > }> > }> }> |
산출
Sending Hi Hi Sent Sending Bye Bye Sent
프로그램을 실행할 때마다 출력은 동일합니다.
설명
위의 예에서는 ThreadedSend 클래스의 run() 메서드 내에서 Sender 개체를 동기화하도록 선택했습니다. 대안적으로 우리는 다음을 정의할 수 있습니다. 전체 send() 블록이 동기화됨 , 동일한 결과를 생성합니다. 그러면 ThreadedSend 클래스의 run() 메소드 내부에서 Message 객체를 동기화할 필요가 없습니다.
// An alternate implementation to demonstrate // that we can use synchronized with method also. class Sender { public synchronized void send(String msg) { System.out.println('Sending ' + msg); try { Thread.sleep(1000); } catch (Exception e) { System.out.println('Thread interrupted.'); } System.out.println('
' + msg + 'Sent'); } } 항상 전체 메소드를 동기화할 필요는 없습니다. 때로는 메소드의 일부만 동기화 . 메소드 내부의 Java 동기화 블록이 이를 가능하게 합니다.
// One more alternate implementation to demonstrate // that synchronized can be used with only a part of // method class Sender { public void send(String msg) { synchronized(this) { System.out.println('Sending ' + msg ); try { Thread.sleep(1000); } catch (Exception e) { System.out.println('Thread interrupted.'); } System.out.println('
' + msg + 'Sent'); } } } 익명 클래스를 사용한 동기화 메소드의 예
자바
// Java Pogram to synchronized method by> // using an anonymous class> import> java.io.*;> class> Test {> > synchronized> void> test_function(> int> n)> > {> > // synchronized method> > for> (> int> i => 1> ; i <=> 3> ; i++) {> > System.out.println(n + i);> > try> {> > Thread.sleep(> 500> );> > }> > catch> (Exception e) {> > System.out.println(e);> > }> > }> > }> }> // Driver Class> public> class> GFG {> > // Main function> > public> static> void> main(String args[])> > {> > // only one object> > final> Test obj => new> Test();> > Thread a => new> Thread() {> > public> void> run() { obj.test_function(> 15> ); }> > };> > Thread b => new> Thread() {> > public> void> run() { obj.test_function(> 30> ); }> > };> > a.start();> > b.start();> > }> }> |
산출
16 17 18 31 32 33