前言
这是一个长篇博客,希望大家关注我并且一起学习java高并发
废话不多说,直接开始
并行和并发
并行:多个线程同时处理多个任务
并发:多个线程处理同个任务,不一定要同时
下面用图来描述并行和并发的区别:
(实现和虚线表示两个不同的线程)
临界区
是受保护的资源,可以被多个线程使用,但是每次只能有一个线程可以使用它
死锁,饥饿,活锁
死锁
因为有些资源的彼此交叉使用,大家都阻塞了线程,所有关于这个资源的线程全部无法工作
饥饿
一个资源被高优先级别的线程不断抢占着,导致低优先级的线程无法工作
某一个线程一致占着资源不放,导致需要这个资源的线程无法正常工作
活锁
多个线程都主动将资源释放给他人使用,就会出现资源不断在两个线程中跳动,而没有一个线程可以正常执行
JMM(java内存模型)
在并行程序中,就是int i =1
都变得及其复杂
下面来看下JMM的三个特性
1. 原子性
和数据库的原子性一样,是指一个操作是不可中断的,即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其它线程干扰
2. 可见性
当一个线程修改了某个共享的值,其它线程是否立即知道这个修改。这个问题在串行程序中是没有的
在并行中实现可见性需要满足以下两个条件:
1.线程修改后的共享变量的值能够及时从工作内存刷新到主内存中
2.其他线程能够及时把共享变量的最新值从主内存更新到自己的工作内存中
因此synchronized实现了可见性和原子性:
对于synchronized的操作JMM有两条规定:
1.线程解锁前,必须把共享变量的最新值刷新到主内存
2.线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需从主内存中重新读取最新的值(加锁与解锁需要同一把锁)
3.有序性
对于串行程序来说,按照顺序进行任务是必然的,但是在并行中却不一样了
比如1号线程要执行两个变量的赋值,但是第一个变量上了锁,要等待解锁,那么它可能就会先对第二个变量进行赋值(这就是指令重排,是jmm特性,可以提高性能)
这时候2号线程去调用一号线程的第一个变量,但1号线程还没有来得及对它赋值,那么这时候就没有保证有序性了。那么为了保证有序性就要用到volatile关键字。
今天就先到这里,大家可以看看这些内容的拓展
记得点关注看更新,谢谢阅读
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。