《Java并发编程的艺术》学习笔记 —— 第1章并发编程的挑战

并发编程的目的:

       并发编程的目的是通过合理的利用,软件与硬件的性能,让程序的运行速度更快,所以并不是启动更多的线程就可以让程序最大程度的并发执行。

上下文切换:

      即使是单核处理器也支持多线程执行代码, 多线程的实现方式是通过CPU给每个线程分配时间片来实现这个机制,因为时间片非常短,所以CPU通过不停的切换时间片,让我们感觉多线程并发执行,时间片一般是几十毫秒(ms)。

      CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片之后会切换到下一个任务,但是切换之前会保存上一 个任务的状态,以便再次切换到这个任务时可以加载这个任务的状态,从当前任务保存状态到加载下一个任务的状态的过程就是一次上下文切换。

 

文中测试多线程与单线程的Demo,因为配置不同所以执行出来的结果也不一致。

package com.yigjn.thread;

/**  

* <p>Title: chapter_01.java</p>  

* <p>Description: </p>  

* <p>Copyright: Copyright (c) 2018</p>  

* @author yigjn

* @date 2019年1月16日  

* @version 1.0  

*/
public class chapter_01 {
	private static final long count = (long) 1e9;  
	
	/**  
	
	 * <p>Title: main</p>  
	
	 * <p>Description: </p>  
	 
	 * @author yigjn  
	
	 * @date 2019年1月16日  
	
	 * @version 1.0  
	 
	 * @param args  
	
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		concurrency();
		serial();
	}

	/**  
	
	 * <p>Title: serial</p>  
	
	 * <p>Description: </p>  
	 
	 * @author yigjn  
	
	 * @date 2019年1月16日  
	
	 * @version 1.0  
	   
	
	 */  
	private static void serial() {
		// TODO Auto-generated method stub
		long start = System.currentTimeMillis();
		int a = 0;
		for (long i = 0; i < count; i++) {
			a += 5;
		}
		System.out.println(a);
		int b = 0;
		for (long i = 0; i < count; i++) {
			b--;
		}
		long time = System.currentTimeMillis() - start;
		System.out.println("serial :" + time + "ms, b = " + b + ", a = " + a);
	}

	/**  
	
	 * <p>Title: concurrency</p>  
	
	 * <p>Description: </p>  
	 
	 * @author yigjn  
	
	 * @date 2019年1月16日  
	
	 * @version 1.0  
	   
	
	 */  
	private static void concurrency() {
		// TODO Auto-generated method stub
		long start = System.currentTimeMillis();
		Thread thread = new Thread(() -> {
			int a = 0;
			for (long i = 0; i < count; i++) {
				a += 5;
			}
			System.out.println(a);
		});
		thread.start();
		int b = 0;
		for (long i = 0; i < count; i++) {
			b--;
		}
		try {
			thread.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		long time = System.currentTimeMillis() - start;
		System.out.println("concurrency :" + time + "ms, b = " + b);
	}

}

如何减少上下文切换:

减少上下文切换的方法有: 无锁多线程并发编程,CAS算法, 单线程编程和使用协程。

  • 无锁并发编程: 多线程竞争同一锁资源时,会产生上下文切换,可以通过数据分段来使不同线程处理不同分段的数据,来避免竞争锁资源造成的上下文切换。

  • CAS算法:Java通过使用Automic包来使用CAS算法来更新数据,从而来去掉加锁,但是要考虑好CAS缺点是否影响程序的执行结果(例如ABA等问题)。

  • 单线程编程:使用最少的线程,在任务很少的情况,尽量减少或者不使用多线程,线程过多,造成大量线程处于waiing状态造成了上下文切换资源损耗。

  • 协程:在单线程里实现多任务调度,并在单线程之间实现多任务之前的切换。

 

展开阅读全文

没有更多推荐了,返回首页