从头认识多线程-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

时间: 2024-10-13 16:03:26

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

从头认识多线程-2.12 synchronized ()代码块不单可以用this,也可以用其他对象

这一章节我们来讨论一下synchronized ()代码块的另一个用法,它不单可以用this,也可以用其他对象. 1.代码清单 package com.ray.deepintothread.ch02.topic_13; /** * * @author RayLee * */ public class ObjectLock { public static void main(String[] args) throws InterruptedException { MyService myServi

java 多线程安全问题-同步代码块

/* 多线程的安全问题: while(true) { if(tick>0) { //线程0,1,2,3在余票为1时,都停滞在这里,之后分别获得CPU执行权,打印出0,-1,-2等错票 System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--); } } 问题的原因: 当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行一部分,还没有执行完,停滞 另一个线程参与进来执行,导致共享数据

java中的静态代码块、构造代码块、普通代码块和同步代码块总结

java中的4中代码块总结如下: * 加了static的是静态代码块,在类中写了一对{}是构造代码块,在方法中写了一对{}是普通代码块, * java中还有一种代码块是同步代码块,常用在多线程中, synchronized关键字, * 同步代码块格式是:synchronized(同步对象){} * 静态代码块 先于构造代码块 先于构造方法执行 * 静态代码块 先于普通代码块 先于构造方法执行 * 构造代码块和普通代码块按照程序逻辑顺序执行 package 面试题; class HelloA{ p

java多线层同时运行的解决,同步代码块synchronized

/* 多个线层同时操作一个数据 会导制数据超出 同步代码块 synchronized(对像) { 需要同步的代码 } */ class Do7 { public static void main(String[] args) { Piao p1=new Piao(); Thread t1=new Thread(p1); Thread t2=new Thread(p1); Thread t3=new Thread(p1); Thread t4=new Thread(p1); t1.start();

2.2.3用同步代码块解决同步方法的弊端

更改2.2.1代码重新测试 package com.cky.utils; /** * Created by chenkaiyang on 2017/12/6. */ public class Task { private String getData1; private String getData2; public void doLongTimeTask() { try { System.out.println("begin task"); Thread.sleep(3000); S

从头认识多线程-2.8 缓解同步方法的隐患-同步代码块

这一章节我们来讨论一下缓解同步方法的隐患-同步代码块. 1.思路:把同步方法,降低同步的粒度,同步到代码块 2.根据上一章节的例子,我们把代码修改一下 (1)第一种方法,把同步标记移到更新的那一栏里面去,一般来说大部分都是更新的时候需要同步数据 package com.ray.deepintothread.ch02.topic_9; /** * 从头认识多线程-2.8 缓解同步方法的隐患-同步代码块<br> * * @author RayLee * */ public class Relief

多线程(同步代码块和同步函数)

线程安全问题 当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,    另一个线程参与进来执行.导致共享数据的错误. 解决办法:    对多条操作共享数据的语句,只能让一个线程都执行完.在执行过程中,其他线程不可以参与执行. Java对于多线程的安全问题提供了专业的解决方式.就是同步代码块. synchronized(对象){    需要被同步的代码}对象如同锁.持有锁的线程可以在同步中执行.没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁.

多线程之同步代码块与同步函数

/*需求:买票分析:多个窗口卖票 是并发的,是多线程利用Runnable接口,传入一个对象,开启多线程 */class Ticket implements Runnable{ private int num=100; Object obj=new Object(); public void run(){ while(true){ synchronized(obj) { if(num>0) { System.out.println(num--+Thread.currentThread().getN

java中多线程模拟(多生产,多消费,Lock实现同步锁,替代synchronized同步代码块)

import java.util.concurrent.locks.*; class DuckMsg{ int size;//烤鸭的大小 String id;//烤鸭的厂家和标号 DuckMsg(){ } DuckMsg(int size, String id){ this.size=size; this.id=id; } public String toString(){ return id + " 大小为:" + size; } } class Duck{ private int