java 다중 루틴 프로그래밍의 Synchronized 블록 동기화 방법
8827 단어 java다중 스레드synchronized
1. synchronized 키워드를 추가할지 여부의 차이
public class ThreadTest {
public static void main(String[] args) {
Example example = new Example();
Thread t1 = new Thread1(example);
Thread t2 = new Thread1(example);
t1.start();
t2.start();
}
}
class Example {
public synchronized void excute() {
for (int i = 0; i < 5; ++i) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("excute:" + i);
}
}
}
class Thread1 extends Thread {
private Example example;
public Thread1(Example example) {
this.example = example;
}
@Override
public void run() {
example.excute();
}
}
synchronized 키워드를 추가한 출력 결과는 다음과 같습니다.0~4 조를 먼저 출력하고 다음 조를 출력하며 두 개의 스레드 순서로 실행합니다
excute:0
excute:1
excute:2
excute:3
excute:4
excute:0
excute:1
excute:2
excute:3
excute:4
synchronized 키워드를 추가하지 않은 출력 결과는 다음과 같습니다.
두 라인이 동시에 excute 방법을 실행하고, 동시에 병행한다
excute:0
excute:0
excute:1
excute:1
excute:2
excute:2
excute:3
excute:3
excute:4
excute:4
2. 여러 가지 방법의 다중 스레드 상황
public class ThreadTest {
public static void main(String[] args) {
Example example = new Example();
Thread t1 = new Thread1(example);
Thread t2 = new Thread2(example);
t1.start();
t2.start();
}
}
class Example {
public synchronized void excute() {
for (int i = 0; i < 5; ++i) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("excute:" + i);
}
}
public synchronized void excute1() {
for (int i = 0; i < 5; ++i) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("excute1:" + i);
}
}
}
class Thread1 extends Thread {
private Example example;
public Thread1(Example example) {
this.example = example;
}
@Override
public void run() {
example.excute();
}
}
class Thread2 extends Thread {
private Example example;
public Thread2(Example example) {
this.example = example;
}
@Override
public void run() {
example.excute1();
}
}
실행 결과는 다음과 같습니다.같은 순서로 실행합니다. 한 라인을 실행하고 다른 라인을 실행합니다.
excute:0
excute:1
excute:2
excute:3
excute:4
excute1:0
excute1:1
excute1:2
excute1:3
excute1:4
synchronized 키워드를 제거하면 두 가지 방법이 동시에 실행되고 서로 영향을 주지 않습니다.
그러나 예제 프로그램에서 설명한 바와 같이 두 가지 방법이라도
실행 결과는 영원히 한 라인의 출력을 끝내고 다른 라인을 실행합니다.
설명:
만약에 한 대상에 여러 개의synchronized 방법이 있다면, 어느 순간에 어떤 라인이 어떤synchronized 방법에 들어갔다면, 이 방법이 실행되기 전에 다른 라인은 이 대상의synchronized 방법에 접근할 수 없습니다.
결론:
synchronized 키워드가 하나의 방법을 수식할 때, 이 방법을 동기화 방법이라고 부른다.
자바의 모든 대상에는 자물쇠(lock) 또는 모니터(monitor)가 있습니다. 한 라인이 특정한 대상의synchronized 방법에 접근할 때 그 대상을 잠그고 다른 어떤 라인도 그 대상의synchronized 방법에 접근할 수 없습니다. (여기는 모든 동기화 방법을 가리키는 것이지 같은 방법이 아니라) 이전의 그 라인 실행 방법이 끝난 후(또는 이상을 던졌을 때까지)이 대상의 자물쇠를 풀어야 다른 라인이 대상의synchronized 방법에 접근할 수 있습니다.
이때 대상의 자물쇠를 잠그고 서로 다른 대상이라면 각 대상 사이에는 제한 관계가 없다.
코드에서 두 번째 루틴 대상을 구성할 때 새로운 Example 대상에 전송하려고 하면 두 루틴의 실행 사이에는 아무런 제약 관계가 없다.
3. 정적 동기화 방법
synchronized 키워드 수식 방법이 static에 의해 수식될 때 이전에 말했듯이 비정적 동기화 방법은 대상을 잠그지만 정적 방법은 대상이 아니라 클래스에 속한다. 이 방법이 있는 클래스의 클래스 대상을 잠그게 된다.
public class ThreadTest {
public static void main(String[] args) {
Example example = new Example();
Example example2 = new Example();
Thread t1 = new Thread1(example);
Thread t2 = new Thread2(example2);
t1.start();
t2.start();
}
}
class Example {
public synchronized static void excute() {
for (int i = 0; i < 5; ++i) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("excute:" + i);
}
}
public synchronized static void excute1() {
for (int i = 0; i < 5; ++i) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("excute1:" + i);
}
}
}
class Thread1 extends Thread {
private Example example;
public Thread1(Example example) {
this.example = example;
}
@Override
public void run() {
example.excute();
}
}
class Thread2 extends Thread {
private Example example;
public Thread2(Example example) {
this.example = example;
}
@Override
public void run() {
example.excute1();
}
}
실행 결과는 다음과 같습니다.excute:0
excute:1
excute:2
excute:3
excute:4
excute1:0
excute1:1
excute1:2
excute1:3
excute1:4
static 수식자가 없으면 두 라인이 각각 다른 대상에 전송되면 동시에 실행됩니다
따라서 정적 방법의 경우(execute ()와execute 2 () 모두static 키워드를 추가), 두 라인에 서로 다른 Example 대상을 전달하더라도 이 두 라인은 서로 제약이 있기 때문에 먼저 하나를 실행하고 다음을 실행해야 한다.
결론:
만약에 어떤synchronized 방법이static라면, 이 방법에 접근할 때, 이 방법은 synchronized 방법이 있는 대상이 아니라,synchronized 방법이 있는 클래스에 대응하는 Class 대상이다.Java에서 한 클래스에 몇 개의 대상이 있든지 간에 이 대상은 유일한 Class 대상에 대응하기 때문에 라인이 같은 클래스의 두 대상의static,synchronized 방법에 각각 접근할 때 그들의 실행 순서도 순서이다. 즉, 한 라인이 먼저 실행 방법에 가고 실행이 끝난 후에 다른 라인이 시작된다는 것이다.
4.synchronized 블록
synchronized(object)
{
}
실행할 때object 대상을 잠그는 것을 나타냅니다.(이 대상은 임의의 종류의 대상일 수도 있고this 키워드를 사용할 수도 있음을 주의하십시오.)
이렇게 하면 스스로 잠금 대상을 규정할 수 있다.
public class ThreadTest {
public static void main(String[] args) {
Example example = new Example();
Thread t1 = new Thread1(example);
Thread t2 = new Thread2(example);
t1.start();
t2.start();
}
}
class Example {
public void excute() {
synchronized (this) {
for (int i = 0; i < 5; ++i) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("excute:" + i);
}
}
}
public void excute1() {
synchronized (this) {
for (int i = 0; i < 5; ++i) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("excute1:" + i);
}
}
}
}
class Thread1 extends Thread {
private Example example;
public Thread1(Example example) {
this.example = example;
}
@Override
public void run() {
example.excute();
}
}
class Thread2 extends Thread {
private Example example;
public Thread2(Example example) {
this.example = example;
}
@Override
public void run() {
example.excute1();
}
}
실행 결과는 다음과 같습니다.excute:0
excute:1
excute:2
excute:3
excute:4
excute1:0
excute1:1
excute1:2
excute1:3
excute1:4
예시 프로그램 4가 달성한 효과는 예시 프로그램 2의 효과와 마찬가지로 두 라인의 실행 순서를 병행하는 것이 아니라 한 라인이 실행될 때object 대상을 잠그고 다른 라인은 대응하는 블록을 실행할 수 없다.
synchronized 방법은 실제적으로synchronized 블록으로 방법의 모든 문장을 감싸고synchronized 블록의 괄호에this 키워드를 전달하는 것과 같다.물론 정적 방법이라면 잠금이 필요한 것은class 대상이다.
한 방법에서 몇 줄의 코드만 라인 동기화 문제와 관련될 수 있기 때문에synchronized 블록은synchronized 방법보다 여러 라인의 접근을 세밀하게 제어하고synchronized 블록의 내용만 여러 라인에 동시에 접근할 수 없으며, 방법의 다른 문장은 여러 라인에 동시에 접근할 수 있다(synchronized 블록 이전과 이후를 포함한다).
결론:
synchronized 방법은 굵은 입도의 병발 제어로 어느 순간에 이 synchronized 방법을 실행하는 라인만 있을 수 있다.
synchronized 블록은 세립도의 병발 제어로 블록의 코드만 동기화할 수 있으며 방법 내,synchronized 블록 이외의 다른 코드는 여러 라인에 동시에 접근할 수 있다.
이상은 자바 다중 루틴 프로그래밍 Synchronized 블록 동기화 방법에 관한 것입니다. 여러분의 학습에 도움이 되기를 바랍니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
38. Java의 Leetcode 솔루션텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.