对于锁的使用,能够让并发,变成序列化 从concurrent-serial
critical section (临界区)没必要放进临界区的代码,就没必要写进去
原子性:上锁之后,代码不可被打断(持有同样的锁的其他代码,打断指的是同时运行)
锁再java中如何实现?
保持某段代码的原子性
Synchronized(经典)
使用jol 来验证 java object layout 包
锁定某个对象是指在这个对象头部header做一些标记
Object o = new Object();在内存中占多少字节
T{ int m; } new T();在内存中占多少字节
T{int m;boolean b; String s ="libo"} new T();在内存中占多少字节
JUC新锁(1.5)
自定义锁
悲观锁、乐观锁、互斥锁、共享锁、读写锁、分段锁
悲观锁:Synchronized()
乐观锁:类似CAS
互斥锁:用这把锁的时候只有一个线程能执行对应的临界区
共享锁:可以有多个线程,使用信号量(semaphore)来标识个数,同时执行的个数
java中目前还没有不可重入锁
自旋锁
自旋锁是根据CAS实现的,映射到底层调用c++ 再到计算机汇编指令 其实就是LOCK+cmpxchg 指令 前面是原子操作 后面不是原子操作的
lock使用缓存锁。 锁总线
锁--cas 有两个问题 ABA问题 适用版本号方式解决或者Boolean类型解决,二是底层两条汇编指令lock+cmpxchg指令 前面是原子操作、后面不是原子操作 靠lock保持原子性 而lock 是依据缓存锁 或者锁总线的方式实现
是不是排队的算法(重量级锁)一定比转圈的算法(轻量级锁)效率高呢?
临界区特别大、执行时间特别长与此同时等待线程特别多,乐观锁(轻量级锁)效率不高,所以要使用排队算法。
锁升级
Synchronized较早的时候是重量级锁,是交给操作系统进行操作的,都是经过OS的
1.4之后经过了优化
轻量级锁自旋次数过多或者自旋数量过多过多的时候这时候 轻量级锁升级为重量级锁
偏向锁 只在第一个线程使用
偏向锁的意义 其实是因为 60%-70%的概率并不会产生锁竞争,当第一个线程来的时候 直接进入即可 不需要复杂的计算。
索引偏向锁 只需要在header中添加一个便签即可。 当失去cpu资源的时候,再重新去竞争资源,发现资源商有标签 就可以直接进入
可重入锁