의 처음 두 섹션에서 - "멀티 스레딩 기본 자바 멀티 스레딩 (가) 학습" 과 "자바 멀티 스레딩 학습 (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의 .
공공 우려 번호에 오신 것을 환영합니다 :