从头认识多线程-2.9 同步代码块的特殊现象:一半同步,一半异步

这一章节我们来讨论一下同步代码块的一个特殊现象:一半同步,一半异步

1.代码清单:

1)目的:展示同步代码块的同步与异步并存的现象

2)代码功能说明:

(1)建立一个测试类

(2)创建三个属性域

(3)创建三个方法,一个同步,两个不同步

(4)方法的内容是输出整数相加的结果以及相应的线程名称

(5)使用两个线程同时访问

package com.ray.deepintothread.ch02.topic_10;

/**
 * 
 * @author RayLee
 *
 */
public class SynchAndAsynch {
	public static void main(String[] args) throws InterruptedException {
		MyService myService = new MyService();
		ThreadOne threadOne = new ThreadOne(myService);
		Thread thread = new Thread(threadOne);
		thread.start();
		ThreadTwo threadTwo = new ThreadTwo(myService);
		Thread thread2 = new Thread(threadTwo);
		thread2.start();
	}
}

class ThreadOne implements Runnable {

	private MyService myService;

	public ThreadOne(MyService myService) {
		this.myService = myService;
	}

	@Override
	public void run() {
		myService.update();
	}
}

class ThreadTwo implements Runnable {

	private MyService myService;

	public ThreadTwo(MyService myService) {
		this.myService = myService;
	}

	@Override
	public void run() {
		myService.update();
	}
}

class MyService {

	private int a = 0;
	private int b = 0;
	private int c = 0;

	private void updateA() {
		for (int i = 0; i < 10; i++) {
			System.out.println("Thread name:" + Thread.currentThread().getName() + " a:" + a++);
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 增加同步
	 */
	private void updateB() {
		for (int i = 0; i < 10; i++) {
			System.out.println("Thread name:" + Thread.currentThread().getName() + " b:" + b++);
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	private void updateC() {
		for (int i = 0; i < 10; i++) {
			System.out.println("Thread name:" + Thread.currentThread().getName() + " c:" + c++);
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public void update() {
		updateA();
		synchronized (this) {
			updateB();
		}
		updateC();
	}
}

输出:

Thread name:Thread-0 a:0
Thread name:Thread-1 a:1
Thread name:Thread-1 a:2
Thread name:Thread-0 a:2
Thread name:Thread-1 a:3
Thread name:Thread-0 a:4
Thread name:Thread-0 a:6
Thread name:Thread-1 a:5
Thread name:Thread-0 a:7
Thread name:Thread-1 a:8
Thread name:Thread-0 a:9
Thread name:Thread-1 a:10
Thread name:Thread-1 a:11
Thread name:Thread-0 a:12
Thread name:Thread-1 a:13
Thread name:Thread-0 a:14
Thread name:Thread-1 a:15
Thread name:Thread-0 a:16
Thread name:Thread-1 a:17
Thread name:Thread-0 a:18

------------------------------------------(人为分隔符)
Thread name:Thread-1 b:0
Thread name:Thread-1 b:1
Thread name:Thread-1 b:2
Thread name:Thread-1 b:3
Thread name:Thread-1 b:4
Thread name:Thread-1 b:5
Thread name:Thread-1 b:6
Thread name:Thread-1 b:7
Thread name:Thread-1 b:8
Thread name:Thread-1 b:9

------------------------------------------(人为分隔符)
Thread name:Thread-0 b:10

Thread name:Thread-1 c:0

Thread name:Thread-0 b:11
Thread name:Thread-1 c:1
Thread name:Thread-1 c:2
Thread name:Thread-0 b:12
Thread name:Thread-0 b:13
Thread name:Thread-1 c:3
Thread name:Thread-1 c:4
Thread name:Thread-0 b:14
Thread name:Thread-1 c:5
Thread name:Thread-0 b:15
Thread name:Thread-0 b:16
Thread name:Thread-1 c:6
Thread name:Thread-1 c:7
Thread name:Thread-0 b:17
Thread name:Thread-0 b:18
Thread name:Thread-1 c:8
Thread name:Thread-1 c:9
Thread name:Thread-0 b:19

------------------------------------------(人为分隔符)
Thread name:Thread-0 c:10
Thread name:Thread-0 c:11
Thread name:Thread-0 c:12
Thread name:Thread-0 c:13
Thread name:Thread-0 c:14
Thread name:Thread-0 c:15
Thread name:Thread-0 c:16
Thread name:Thread-0 c:17
Thread name:Thread-0 c:18
Thread name:Thread-0 c:19


2.分析

我们把上面的输出分为4段:

(1)第一段

Thread name:Thread-0 a:0
Thread name:Thread-1 a:1
Thread name:Thread-1 a:2
Thread name:Thread-0 a:2
Thread name:Thread-1 a:3
Thread name:Thread-0 a:4
Thread name:Thread-0 a:6
Thread name:Thread-1 a:5
Thread name:Thread-0 a:7
Thread name:Thread-1 a:8
Thread name:Thread-0 a:9
Thread name:Thread-1 a:10
Thread name:Thread-1 a:11
Thread name:Thread-0 a:12
Thread name:Thread-1 a:13
Thread name:Thread-0 a:14
Thread name:Thread-1 a:15
Thread name:Thread-0 a:16
Thread name:Thread-1 a:17
Thread name:Thread-0 a:18

这一段输出结合代码我们可以知道,这个时候是两个线程同时访问updateA这个方法,由于该方法没有做同步,因此会出现上面的间隔的输出


(2)第二段

Thread name:Thread-1 b:0
Thread name:Thread-1 b:1
Thread name:Thread-1 b:2
Thread name:Thread-1 b:3
Thread name:Thread-1 b:4
Thread name:Thread-1 b:5
Thread name:Thread-1 b:6
Thread name:Thread-1 b:7
Thread name:Thread-1 b:8
Thread name:Thread-1 b:9

这一段输出,由于updateB做了同步,这个时候Thread-1拿到锁,因此Thread-0想访问updateB就不行,只好等Thread-1执行完成才可以。


(3)第三段

Thread name:Thread-0 b:10

Thread name:Thread-1 c:0

Thread name:Thread-0 b:11
Thread name:Thread-1 c:1
Thread name:Thread-1 c:2
Thread name:Thread-0 b:12
Thread name:Thread-0 b:13
Thread name:Thread-1 c:3
Thread name:Thread-1 c:4
Thread name:Thread-0 b:14
Thread name:Thread-1 c:5
Thread name:Thread-0 b:15
Thread name:Thread-0 b:16
Thread name:Thread-1 c:6
Thread name:Thread-1 c:7
Thread name:Thread-0 b:17
Thread name:Thread-0 b:18
Thread name:Thread-1 c:8
Thread name:Thread-1 c:9
Thread name:Thread-0 b:19

这一段也是间隔输出,但其中的原理跟第一段其实是不一样的。

对于Thread-0,由于上一阶段没有拿到锁,这个阶段才拿到,因此,它还在同步的执行updateB这个方法

对于Thread-1,由于上一阶段已经完成同步方法,这个阶段执行不同步的updateC,所以会间隔的穿插输入

这一阶段就是我们所需要展示的一半同步,一半异步的现象


(4)第四段

Thread name:Thread-0 c:10
Thread name:Thread-0 c:11
Thread name:Thread-0 c:12
Thread name:Thread-0 c:13
Thread name:Thread-0 c:14
Thread name:Thread-0 c:15
Thread name:Thread-0 c:16
Thread name:Thread-0 c:17
Thread name:Thread-0 c:18
Thread name:Thread-0 c:19

虽然看上去跟第二段差不多,但是原理也是不一样

这里只是Thread-1已经完成了所有功能,只剩下Thread-0的执行了。


总结:这一章节展示了不同步、同步以及一半半的情况。


这一章节就到这里,谢谢

------------------------------------------------------------------------------------

我的github:https://github.com/raylee2015/DeepIntoThread


目录:http://blog.csdn.net/raylee2007/article/details/51204573


你可能感兴趣的:(多线程)