멀티스레드 처음 인식-2.3 더티(dirty Read)

4529 단어 다중 스레드
이 섹션에서는 더티(dirty Read)에 대해 설명합니다.
1.왜 더러운 독서가 나오는가?
코드가 동기화되지 않았기 때문에 set 방법이 동기화되었지만 get 방법은 일반적으로 잊어버리기 때문에 읽은 값이 쓰여진 것입니다
2. 코드 목록
(1) 프로그램이 동기화되지 않고 너무 빨리 실행되어 더티(dirty) 읽기
package com.ray.deepintothread.ch02.topic_4;

public class DirtyRead {
	public static void main(String[] args) throws InterruptedException {
		MyTestObjectOne myTestObjectOne = new MyTestObjectOne();
		ThreadOne threadTwo = new ThreadOne(myTestObjectOne);
		Thread thread = new Thread(threadTwo);
		thread.start();
		System.out.println("id:" + myTestObjectOne.getId() + " name:" + myTestObjectOne.getName());
	}
}

class ThreadOne implements Runnable {

	private MyTestObjectOne myTestObjectOne;

	public ThreadOne(MyTestObjectOne myTestObjectOne) {
		this.myTestObjectOne = myTestObjectOne;
	}

	@Override
	public void run() {
		myTestObjectOne.setId(1);
		myTestObjectOne.setName("ray");
	}
}

class MyTestObjectOne {
	private int id = 0;
	private String name = "init";

	public int getId() {
		return id;
	}

	public synchronized void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public synchronized void setName(String name) {
		this.name = name;
	}
}

출력:
id:0 name:init
동기화되지 않았기 때문에 set의 라인이 시작될 때 get이 초기화된 값을 나타냅니다
(2) 동기화되지 않아 코드의 실행 선후 순서와 실행 시간을 제어할 수 없기 때문에 읽은 값은 이미 수정된 것이다
package com.ray.deepintothread.ch02.topic_4;

public class DirtyRead2 {
	public static void main(String[] args) throws InterruptedException {
		MyTestObjectTwo myTestObjectTwo = new MyTestObjectTwo();
		ThreadTwo threadTwo = new ThreadTwo(myTestObjectTwo);
		Thread thread = new Thread(threadTwo);
		thread.start();
		Thread.sleep(100);//       ,         ,             
		System.out.println("id:" + myTestObjectTwo.getId() + " name:" + myTestObjectTwo.getName());
	}
}

class ThreadTwo implements Runnable {

	private MyTestObjectTwo myTestObjectTwo;

	public ThreadTwo(MyTestObjectTwo myTestObjectTwo) {
		this.myTestObjectTwo = myTestObjectTwo;
	}

	@Override
	public void run() {
		myTestObjectTwo.setId(1);
		try {
			Thread.sleep(1000);//       
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		myTestObjectTwo.setName("ray");
	}
}

class MyTestObjectTwo {
	private int id = 0;
	private String name = "init";

	public int getId() {
		return id;
	}

	public synchronized void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public synchronized void setName(String name) {
		this.name = name;
	}
}

출력:
id:1 name:init
출력에서 id가 수정되었지만,name를 수정하지 않았을 때, 이미 읽기 시작했음을 알 수 있습니다.
3. 솔루션 - 동기화, 그리고 기교 있는 동기화
package com.ray.deepintothread.ch02.topic_4;

public class DirtyRead3 {
	public static void main(String[] args) throws InterruptedException {
		MyTestObjectThree myTestObjectThree = new MyTestObjectThree();
		ThreadThree threadThree = new ThreadThree(myTestObjectThree);
		Thread thread = new Thread(threadThree);
		thread.start();
		ThreadFour threadFour = new ThreadFour(myTestObjectThree);
		Thread thread1 = new Thread(threadFour);
		thread1.start();
	}
}

class ThreadThree implements Runnable {

	private MyTestObjectThree myTestObjectThree;

	public ThreadThree(MyTestObjectThree myTestObjectThree) {
		this.myTestObjectThree = myTestObjectThree;
	}

	@Override
	public void run() {
		myTestObjectThree.setValue(1, "ray");
	}
}

class ThreadFour implements Runnable {

	private MyTestObjectThree myTestObjectThree;

	public ThreadFour(MyTestObjectThree myTestObjectThree) {
		this.myTestObjectThree = myTestObjectThree;
	}

	@Override
	public void run() {
		myTestObjectThree.getValue();
	}
}

class MyTestObjectThree {
	private int id = 0;
	private String name = "init";

	public synchronized void setValue(int id, String name) {
		this.id = id;
		this.name = name;
	}

	public synchronized void getValue() {
		System.out.println("id:" + id + " name:" + name);
	}
}

출력:
id:1 name:ray
동기화는 확실히 위의 문제를 해결할 수 있지만 주의해야 할 것은 위의 set 방법은 두 속성을 함께 설정한 것이다. 만약에 분리된다면 안 된다. 같은 이치로 get의 방법은 둘을 동시에 얻을 수 있고 분리하는 것은 안 된다.
총괄: 이 장에서 우리는 더러운 독서의 형성과 해결 방안을 토론했다.
이 장은 여기까지입니다. 감사합니다.
------------------------------------------------------------------------------------
내 github:https://github.com/raylee2015/DeepIntoThread
디렉토리:http://blog.csdn.net/raylee2007/article/details/51204573

좋은 웹페이지 즐겨찾기