线程和进程是什么
进程:
是操作系统调度和资源分配的最小单位,是程序的实体;首先这个实体有自己的地址空间,文本区域(存储处理器要执行的代码),数据区域(变量和进程执行期间使用的动态分配的内存),堆栈(本地变量和执行过程中调用的指令),其次这个实体被操作系统执行.我们才叫他—进程.
线程:
操作系统运算调度的基本单位,被包含在进程内;有的操作系统把进程作为线程的容器;
多线程就是线程的某部分代码和其他线程的这部分代码互斥执行
如何减少上下文切换?
多线程比较耗费资源的地方之一是上下文切换,就像我们人脑一样,如果同时处理很多事情,十分耗费精神
多线程也不一定就比单线程快,如果线程操作的资源紧缺,或者资源有限,单线程可能还会快一点.
由于线程切换很耗费性能,所以线程的数量把控是比较关键的.
- 控制线程数量–最少线程
- 无锁并发–不同数据段使用不同的线程
- 使用CAS算法,用CAS操作更新数据
- 协程–单线程实现多任务,单线程多任务切换
volatile
olatile关键字其实主要两个点:
- 立即把缓存中的数据回写到内存
- 使其他线程的缓存失效
就是实现一种可见性,当cpu1操作了i变量后,立即把i回写到内存,然后通过总线使cpu2和cpu3的高速缓存失效,然后再重新去内存读取到自己的高速缓存
synchronized 和cas操作
原理:Java的每个对象都可以作为锁
这个关键字三种用法:
- 修饰普通方法,锁住当前实例
- 修饰静态方法,锁住当前类
- 修饰方法块,锁住方法块里面配置的对象
JVM基于进入和退出Monitor对象来实现方法和代码块同步
如果是代码块则是进入的时候有一个monitorenter,离开就是monitorquit,
这个关键字是基于锁机制的 - CAS操作(Compare and swap)
就是比较并交换,比较就有问题,比较出来一样不就不换了吗,所以这个会加一个版本号,在Angular里面,@output,@Input的时候,遇到值没有改变的时候,还有NgmodelChange我个人认为也是CAS操作相似的这种;但是后来发现Input值不改变的时候触发不了,就换别的方法在组件间传值了
Java对象头
synchronized 的锁放Java对象头的,这个头默认存储对象的hashcode,分代年龄,锁标志位
Java锁
Java里面的锁有四种状态,锁是只可以升级,不能降级的
- 无锁
- 偏向锁
这个锁一般用于线程竞争资源不激烈的情况,大部分都是同一个线程去请求锁,所以就在对象头的Markword去存储获得偏向锁的线程id,如果有其他线程来竞争, 竞争激烈就会升级为轻量级锁
获取锁:当线程进入同步块或者方法的时候,会在对象头的锁记录里面存储偏向的线程id,当线程再次进入或退出的时候就只需要去看对象头存的线程id是不是自己的,是的话就表示获取锁成功,不是得话还得去看看对象头的锁标志位看看现在是不是偏向锁,不是就CAS操作竞争资源,是就换成自己的线程id,用CAS操作 - 轻量级锁
把对象头存锁的那个复制到线程里面,然后在对象头装指向这个位置的指针,其他线程要这个锁的时候就自己转着玩儿(自旋),等那个有获得了锁的线程还回来之后,等待的线程再去复制对象头的,用的是cas操作,但是当线程还锁的时候,如果失败了就要升级成重量级锁,但是为什么会失败呐 - 重量级锁