java并发----初识+并发编程引起的挑战

为了让程序运行的更快,引入多线程。并不是启用更多的线程就会提高程序的运行速度。并发编程会有很多挑战。比如上下文切换,死锁问题。

上下文切换

cpu是通过时间片流转的方式分配线程完成任务。当一个时间片完成之后,会切换到另一个线程的任务,此时就需要保存刚刚未完成的任务的环境等,操作系统的知识 该东西被存在pcb中 ,以便在切回这个线程时可以继续,这个过程被称为上下文切换。

上下文如何切换,便是一个多线程可以高效完成任务的关键。

多线程不一定比单线程快的,并发累计操作不超过百万时,比串行慢。原因就是上下文的切换和创建线程的开销。

关于上下文的测试 有几个工具。

Lmbench3 可以测试上下文切换的时长

vmstat 测试上下文切换的次数

减少上下文的切换

无锁并发编程,CAS算法,使用最少线程 ,使用协程

无锁并发编程

使用Hash 将数据的id分段, 不同的线程处理不同的数据

CAS算法

Atomic的CAS 算法 ,不需要加锁 。乐观锁实现的一种方法,但是有可能长时间自旋,增加cpu的开销。 原理就是在更新数据之前要检查是否跟之前的值相同 ,是则更新原值。理论上需要三个数值,一个内存值,预期的原值,和新值,如果预期的原值和内存值相同,更新新值到内存中。

cas存在的问题:

扫描二维码关注公众号,回复: 16538851 查看本文章
  1. ABA :就是说 因为CAS算法会在更新前比较值,比较的时候两个值看起来相同,比方说都是a ,但是有可能在这个过程中他已经先被改成b 又改回 a 那么cas就会认为它是没有被改变的,由此出现问题。这个问题的解决方法就是利用版本号机制,就是说每次更改留下一个版本号。
  2. 长时间循环自旋:就是说CAS可能长时间不成功,就会自旋 增加cpu的开销。
  3. 他只能同时保证一个共享变量的原子操作。  但是从1.5之后 一个AomicReference类的出现保证引用对象的原子性,可以把多个共享变量放在同一个对象中进行CAS操作 

使用最少线程

避免创建没必要的线程。

协程

在单线程里实现多任务的调度,维持多个任务的切换。

死锁

按照操作系统的定义:当一个线程无限期等待另一个线程所占有的不会释放的资源,就会引起死锁问题。出现死锁时 可以用dump线程来查看到底是哪出现了死锁

避免死锁的几个方法:

  1. 避免线程同时获取多个锁
  2. 避免一个线程在锁内同时占用多个资源
  3. 使用定时锁
  4. 对于数据库锁,加锁解锁要在一个数据库连接中

资源的限制

比如一些硬件的问题了。

猜你喜欢

转载自blog.csdn.net/Yoke______/article/details/123228507