자바 멀티 스레딩 학습 (3 개) - 동기 (에)

의 처음 두 섹션에서 - "멀티 스레딩 기본 자바 멀티 스레딩 (가) 학습""자바 멀티 스레딩 학습 (2 개) - 도입의 Thread 클래스의 방법을" 우리는 안전 스레드 및 비 스레드 안전의 개념에 연락 섹션은 동기화 된 키워드의 사용에 대해 배울 수있다.

1 스레드 안전 변수

이 방법은 개인 변수, 내부가 "비 스레드 안전"문제의 "인스턴스 변수"에 존재하는 "비 스레드 안전"문제는 존재하지 않습니다. 두 스레드가 동시에 객체 인스턴스 변수를 운영하는 경우, 비 스레드 안전에 문제가있을 것입니다,이 솔루션은 방법에 동기화 동기화 키워드를 추가 컨트롤을 추가하는 것입니다.

2 잠금 여러 개체 복수

코드를 살펴 :

public class HasSelfPrivateNum {
    // 创建被同步关键字修饰的方法
    private int num = 0;
    synchronized public void add(String name){

        try {
            if ("a".equals(name)){
                num = 100;
                System.out.println("a set over");
                Thread.sleep(2000);
            }else {
                num = 200;
                System.out.println("b set over");
            }
            System.out.println(name + " num = " + num);
        }catch (InterruptedException e){
            e.printStackTrace();
        }

    }
}
public class ThreadA extends Thread {
// 创建线程,构造器传参为上面方法的对象
    private HasSelfPrivateNum hasSelfPrivateNum;

    public ThreadA(String name, HasSelfPrivateNum hasSelfPrivateNum){
        super();
        this.hasSelfPrivateNum = hasSelfPrivateNum;
        this.setName(name);
    }

    @Override
    public void run() {
        super.run();
        hasSelfPrivateNum.add(this.getName());
    }
}
// main方法和输出
 public static void main(String[] args){
        HasSelfPrivateNum hasSelfPrivateNum = new HasSelfPrivateNum();
        HasSelfPrivateNum hasSelfPrivateNum1 = new HasSelfPrivateNum();
        ThreadA threadA = new ThreadA("a", hasSelfPrivateNum);
        ThreadA threadA1 = new ThreadA("b", hasSelfPrivateNum1);
        threadA.start();
        threadA1.start();
    }

b set over
a set over
b num = 200
a num = 100

예로서 두 개의 자물쇠가 있도록, 두 HasSelfPrivateNum 객체를 생성하므로 결과를 비동기식으로 실행된다.

잠금 오히려 코드 또는 방법의 잠금 부재로서보다 대물 로크를 얻기 위해 동기화된다. 여러 스레드가 같은 액세스하는 경우 따라서 위의 예에서, 스레드의 첫 번째 구현은 동기화 된 키워드와 잠금 방법을 잠 그려면, 다음 방법은 객체에 속하는 수용하는 스레드는 다음 다른 스레드는 상태로 대기 할 수 있습니다 객체. 여러 스레드가 여러 개체에 액세스하는 경우, JVM은 여러 잠금을 만듭니다.

주된 방향이 조금 변경 :

public static void main(String[] args){
        HasSelfPrivateNum hasSelfPrivateNum = new HasSelfPrivateNum();
        //HasSelfPrivateNum hasSelfPrivateNum1 = new HasSelfPrivateNum();
        ThreadA threadA = new ThreadA("a", hasSelfPrivateNum);
        ThreadA threadA1 = new ThreadA("b", hasSelfPrivateNum);
        threadA.start();
        threadA1.start();
    }
----
a set over
a num = 100
b set over
b num = 200

그리고 threadA threadA1 개체의 잠금, 그것은 출력의 순서입니다 얻을 볼 수 있습니다.

도 3에서, 오브젝트의 메소드와 동기화

위를 통해 우리는 객체가 동기화 잠금이 아니라 코드 또는 잠금 방법의 조각 같은보다 취득 잠글 것을 알고있다. 다중 스레드 동기화 된 키워드와 상기 방법을 수행하는 쓰레드와 동일한 개체에 액세스하는 경우,이 방법을 수용하는 스레드는 다른 스레드 만 대기 상태에있을 수있다. 다중 스레드는 하나 이상의 개체가 여러 개의 잠금이 때문에 객체가 반드시 더없는 액세스합니다.

여러 스레드가 동기화 된 키워드가 수정 된 방법, 스레드 비동기 호출 수정되지 않은 방법에서 같은 객체가 아닌 액세스하는 경우.

4, 더러운 읽기

과제를 동시에 수행하는 경우이 경우의 값이 더티 읽기 때, 그러나 예상치 못한 놀라움이있을 수 있습니다. 더티 판독의 경우이 값은 다른 스레드에 의해 수정되어, 인스턴스 변수를 판독 일어난다.

public class DirtyReadTest {
    // 创建同步修改数据方法,非同步取数据方法
    public String username = "A";
    public String password = "AA";
    synchronized public void setValue(String username, String password){
        try {
            this.username = username;
            Thread.sleep(5000);
            this.password = password;
            System.out.println("setValue method: username = " + username + " password = " + password);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }

    public void getValue(){
        System.out.println("getValue method: username = " + username + " password = " + password);
    }

}
public class ThreadTest extends Thread {
    private DirtyReadTest dirtyReadTest;
    public ThreadTest(DirtyReadTest dirtyReadTest){
        super();
        this.dirtyReadTest=dirtyReadTest;
    }

    @Override
    public void run() {
        super.run();
        dirtyReadTest.setValue("B", "BB");
    }
}

출력 :

public static void main(String[] args) throws Exception{
        DirtyReadTest dirtyReadTest = new DirtyReadTest();
        ThreadTest threadTest = new ThreadTest(dirtyReadTest);
        threadTest.start();
        Thread.sleep(200);
        dirtyReadTest.getValue();
    }
getValue method: username = B password = AA
setValue method: username = B password = BB

이 솔루션은을 getValue 방법에 동기화 된 키워드를 추가하는 것입니다.

오브젝트 A는 스레드 1 (2)가 오브젝트의 임의의 방법 변성 동기를 획득 할 수없는 쓰레드 인 객체의 잠금을 획득 할 경우에있어서 나사 1 호출 동기화 아닌 경우 동기화 수정 방법은 액세스 될 수있다.

5, 동기화 잠금 재진입

스레드는 오브젝트의 로크가 획득 될 때, 동기화 사용시, 다시 요청 객체의 로크가 다시 획득 될 수 있고, 방출하지 않는다. 하지 재진입 잠금 데드락이 발생할 수있는 경우 객체에 액세스 할 수있는 개체의 방법의 동기화 된 변형은 다른 방식으로 수정 된 동기화된다.

시험 방법 :

public class Service {
    synchronized public void service1(){
        System.out.println("service1");
        service2();
    }

    synchronized public void service2(){
        System.out.println("service2");
        service3();
    }

    synchronized public void service3(){
        System.out.println("service3");

    }
}
public class ThreadTest extends Thread {
    @Override
    public void run() {
        super.run();
        Service service = new Service();
        service.service1();
    }
}
public static void main(String[] args){
        ThreadTest threadTest = new ThreadTest();
        threadTest.start();
    }

service1
service2
service3

재진입 잠금 장치는 환경을 상속 부모 - 자식 클래스에서 지원되고, 서브 클래스는 재진입 잠금 장치를 통해 호출 부모 클래스를 동기화 할 수 있습니다. 이것은 당신이 자기가 쓴 쓸 수 있습니다 더 이상 코드를 작성하지 않습니다.

6 이상, 자동 릴리스

스레드 예외 코드 실행이 발생하면, 모든 잠금이 자동으로 해제됩니다.

7, 동기화는 상속이 없습니다

부모 클래스는 동기화 된 키워드와 방법이있는 경우, 서브 클래스는 상속이 메소드를 오버라이드 (override). 그러나 동기화는 여전히 서브 클래스의 방법으로 동기화 키워드를 추가 할 필요가 상속 될 수 없습니다.

코드의이 섹션 GitHub의 .


공공 우려 번호에 오신 것을 환영합니다 :
어떤 마이크로 채널을 공개하지

추천

출처blog.csdn.net/qq_36447151/article/details/93708687