자바의synchronized 키워드
9069 단어 javasynchronized
1. 두 개의 병렬 라인이 같은 대상object에 있는synchronized (this) 동기화 코드 블록에 접근할 때 한 시간 안에 한 라인만 실행될 수 있습니다.다른 라인은 현재 라인이 이 코드 블록을 실행한 후에야 이 코드 블록을 실행할 수 있습니다.
2. 그러나, 한 라인이object의synchronized (this) 동기화 코드 블록에 접근할 때, 다른 라인은 이 object의 비synchronized (this) 동기화 코드 블록에 접근할 수 있다.
3. 특히 관건적인 것은, 하나의 라인이object의synchronized(this) 동기화 코드 블록에 접근할 때, 다른 라인이object의 모든 다른synchronized(this) 동기화 코드 블록에 대한 접근이 막힐 것이다.
넷째, 세 번째 예는 다른 동기화 코드 블록에도 적용된다.즉, 하나의 라인이object의synchronized (this) 동기화 코드 블록에 접근할 때, 이object의 대상 자물쇠를 얻을 수 있다.결과적으로 다른 라인이 이object 대상의 모든 동기화 코드 부분에 대한 접근이 일시적으로 막혔습니다.
5. 상기 규칙은 다른 대상의 자물쇠에도 적용된다.
예제 설명:
1. 두 개의 병렬 라인이 같은 대상object에 있는synchronized (this) 동기화 코드 블록에 접근할 때 한 시간 안에 한 라인만 실행될 수 있습니다.다른 라인은 현재 라인이 이 코드 블록을 실행한 후에야 이 코드 블록을 실행할 수 있습니다.
package ths;
public class Thread1 implements Runnable {
public void run() {
synchronized(this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);
}
}
}
public static void main(String[] args) {
Thread1 t1 = new Thread1();
Thread ta = new Thread(t1, "A");
Thread tb = new Thread(t1, "B");
ta.start();
tb.start();
}
}
결과:A synchronized loop 0
A synchronized loop 1
A synchronized loop 2
A synchronized loop 3
A synchronized loop 4
B synchronized loop 0
B synchronized loop 1
B synchronized loop 2
B synchronized loop 3
B synchronized loop 4
2. 그러나, 한 라인이object의synchronized (this) 동기화 코드 블록에 접근할 때, 다른 라인은 이 object의 비synchronized (this) 동기화 코드 블록에 접근할 수 있다.
package ths;
public class Thread2 {
public void m4t1() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public void m4t2() {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
final Thread2 myt2 = new Thread2();
Thread t1 = new Thread( new Runnable() { public void run() { myt2.m4t1(); } }, "t1" );
Thread t2 = new Thread( new Runnable() { public void run() { myt2.m4t2(); } }, "t2" );
t1.start();
t2.start();
}
}
결과:t1 : 4
t2 : 4
t1 : 3
t2 : 3
t1 : 2
t2 : 2
t1 : 1
t2 : 1
t1 : 0
t2 : 0
3. 특히 관건적인 것은, 하나의 라인이object의synchronized(this) 동기화 코드 블록에 접근할 때, 다른 라인이object의 모든 다른synchronized(this) 동기화 코드 블록에 대한 접근이 막힐 것이다.
Thread2 수정하기2.m4t2() 메서드:
public void m4t2() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
결과:t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
넷째, 세 번째 예는 다른 동기화 코드 블록에도 적용된다.즉, 하나의 라인이object의synchronized (this) 동기화 코드 블록에 접근할 때, 이object의 대상 자물쇠를 얻을 수 있다.결과적으로 다른 라인이 이object 대상의 모든 동기화 코드 부분에 대한 접근이 일시적으로 막혔습니다.
Thread2 수정하기2.m4t2() 방법은 다음과 같습니다.
public synchronized void m4t2() {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
결과:t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
5. 상기 규칙은 다른 객체 잠금에도 적용됩니다.
package ths;
public class Thread3 {
class Inner {
private void m4t1() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
private void m4t2() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
}
private void m4t1(Inner inner) {
synchronized(inner) { //
inner.m4t1();
}
private void m4t2(Inner inner) {
inner.m4t2();
}
public static void main(String[] args) {
final Thread3 myt3 = new Thread3();
final Inner inner = myt3.new Inner();
Thread t1 = new Thread( new Runnable() {public void run() { myt3.m4t1(inner);} }, "t1");
Thread t2 = new Thread( new Runnable() {public void run() { myt3.m4t2(inner);} }, "t2");
t1.start();
t2.start();
}
}
결과:비록 스레드 t1은 Inner에 대한 대상 자물쇠를 얻었지만, 스레드 t2는 같은 Inner의 비동기적인 부분을 방문하기 때문이다.그래서 두 라인은 서로 방해하지 않는다.
t1 : Inner.m4t1()=4
t2 : Inner.m4t2()=4
t1 : Inner.m4t1()=3
t2 : Inner.m4t2()=3
t1 : Inner.m4t1()=2
t2 : Inner.m4t2()=2
t1 : Inner.m4t1()=1
t2 : Inner.m4t2()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=0
지금 이너에 있어요.m4t2() 앞에 synchronized:
private synchronized void m4t2() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
결과:비록 루트 t1과 t2는 같은 Inner 대상 중 두 개의 상관없는 부분을 방문했지만 t1은 먼저 Inner에 대한 대상 자물쇠를 얻었기 때문에 t2는 Inner에 대한 자물쇠를 얻었다.m4t2()의 접근도 막혔다. 왜냐하면 m4t2()는 Inner의 동기화 방법이기 때문이다.
t1 : Inner.m4t1()=4
t1 : Inner.m4t1()=3
t1 : Inner.m4t1()=2
t1 : Inner.m4t1()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=4
t2 : Inner.m4t2()=3
t2 : Inner.m4t2()=2
t2 : Inner.m4t2()=1
t2 : Inner.m4t2()=0
synchronized 키워드, 두 가지 용법을 포함합니다:synchronized 방법과synchronized 블록.
1.synchronized 방법: 방법 성명에 synchronized 키워드를 넣어synchronized 방법을 설명합니다.예:
public synchronized void accessVal(int newVal);
synchronized 방법은 클래스 구성원 변수에 대한 접근을 제어합니다. 모든 클래스는 하나의 자물쇠에 대응하고, 모든 synchronized 방법은 반드시 이 방법을 호출하는 클래스 실례의 자물쇠를 얻어야 실행할 수 있습니다. 그렇지 않으면 소속 루트가 막힙니다. 방법이 실행되면 이 자물쇠를 독점하고 이 방법에서 돌아올 때까지 자물쇠를 방출합니다. 이후에 막힌 루트는 이 자물쇠를 얻어서 다시 실행 가능한 상태로 들어갈 수 있습니다.이러한 메커니즘은 같은 시각에 모든 클래스 실례에 대해synchronized라고 성명된 구성원 함수 중 하나는 실행 가능한 상태이기 때문에 (이 클래스 실례에 대응하는 자물쇠를 얻을 수 있기 때문에) 클래스 구성원 변수의 접근 충돌을 효과적으로 피할 수 있다. (클래스 구성원 변수에 접근할 수 있는 모든 방법이 synchronized라고 성명된다면)
자바에서 클래스의 실례뿐만 아니라 모든 클래스도 자물쇠에 대응한다. 그러면 우리는 클래스의 정적 구성원 함수를synchronized로 성명하여 클래스의 정적 구성원 변수에 대한 접근을 제어할 수 있다.
synchronized 방법의 결함: 만약에 큰 방법을synchronized라고 성명하면 효율에 큰 영향을 줄 수 있다. 전형적으로 라인 클래스의 방법run()을synchronized라고 성명하면 라인의 전체 생명 기간 동안 계속 실행되기 때문에 이 클래스의synchronized 방법에 대한 호출은 영원히 성공하지 못할 것이다.물론 우리는 접근 클래스 구성원 변수의 코드를 전문적인 방법에 넣어synchronized라고 설명하고 주 방법에서 호출해서 이 문제를 해결할 수 있지만, 자바는 우리에게 더 좋은 해결 방법을 제공했다. 그것이 바로synchronized 블록이다.
2.synchronized 블록:synchronized 키워드를 통해synchronized 블록을 설명합니다.구문은 다음과 같습니다.
synchronized(syncObject) {
//액세스 제어 코드
}
synchronized 블록은 이러한 코드 블록이다. 그 중의 코드는 대상synchObject(전에서 말한 바와 같이 클래스 실례나 클래스일 수 있음)의 자물쇠를 얻어야 실행할 수 있고 구체적인 메커니즘은 앞에서 말한 것과 같다.임의의 코드 블록에 대해 임의로 지정할 수 있고 잠긴 대상을 임의로 지정할 수 있기 때문에 유연성이 비교적 높다.
이상은 자바synchronized 키워드에 대한 상세한 실례 소개입니다. 여러분이synchronized 키워드의 사용법을 더욱 잘 배울 수 있도록 도와주시기 바랍니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
38. Java의 Leetcode 솔루션텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.