JAVA多线程
Posted 代号菜鸟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA多线程相关的知识,希望对你有一定的参考价值。
主要内容在 http://www.tuicool.com/articles/yiyy6bI 基础上拓展。
JAVA中的多线程操作一般采用锁来保证线程安全。
常用的方法有:synchronized, lock。但是这种锁是一种独占锁,悲观锁。
虽然保证了线程安全,但是存在下面几个问题:
在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。
一个线程持有锁会导致其它所有需要此锁的线程挂起。
如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险。
而另一个更加有效的锁就是乐观锁。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。
参考 http://www.importnew.com/18126.html 深入理解。
与锁相比, volatile
变量是一个更轻量级的同步机制,是一种免锁机制。
在使用这些变量时不会发生上下文切换和线程调度等操作,相对于上面提到的锁机制,效率更高。
但是 volatile
不能解决原子性问题,因此当一个变量依赖旧值时就不能使用 volatile
变量。
原子性:一个线程进行操作的过程中,其他线程不能打断。
乐观锁是一种解决方案
相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。
具体实现细节:主要就是两个步骤:冲突检测和数据更新。其实现方式有一种比较典型的就是 Compare and Swap ( CAS
)。
CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。
CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。
如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。
无论哪种情况,它都会在 CAS 指令之前返回该位置的值。(在 CAS 的一些特殊情况下将仅返回 CAS 是否成功,而不提取当前值。)
CAS 有效地说明了“ 我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。 ”这其实和乐观锁的冲突检查+数据更新的原理是一样的。
http://blog.csdn.net/heyutao007/article/details/19975665 详细介绍了乐观锁的工作原理。
在实际生产环境里边,如果并发量不大且不允许脏读,可以使用悲观锁解决并发问题;但如果系统的并发非常大的话,悲观锁定会带来非常大的性能问题,所以我们就要选择乐观锁定的方法.
有一篇文章写得十分详细: http://www.importnew.com/18126.html
以上是关于JAVA多线程的主要内容,如果未能解决你的问题,请参考以下文章