synchronized优化
在JDK1.5中,synchronized还性能较低的,因为只是一个重量级操作,synchronized是一个重量级锁,就是多个线程只有一个线程能够获取到锁,未获取到锁的线程将会被阻塞,等到持有锁的线程释放锁后,这些线程又被唤醒,这些操作非常耗费CPU的资源
IDK1.6对synchronized做了优化
CAS:乐观锁
- 乐观锁:假设所有线程访问共享资源时不会出现冲突(多个线程不同时间访问同一资源),既然不会出现冲突自然就不会阻塞其他线程。线程就不会出现阻塞状态。
- 悲观锁(JDK1.6之前的内建锁):假设每一次执行同步代码块均会产生冲突,所以当线程获取锁成功,会阻塞其他尝试获取该锁的线程。
无锁操作使用CAS来鉴别线程是否出现冲突,若发生冲突就重试当前操作直到不冲突为止
CAS操作:
V:内存中地址存放的实际值
O:预期值(旧值)
N:更新后的值
当执行CAS后:
- 若V==O,即旧值与内存中实际值相等,表示上次修改该值后没有任何线程再次修改该值,因此可以将N替换到内存中。
- 若V!=O,表示内存中的值已经被其他线程修改,所以无法将N替换,返回最新的值V。
当多个线程使用CAS操作同一个变量时,只有一个线程会成功,并成功更新变量值,其余线程均会失败。失败线程会重新尝试或将线程挂起。
CAS存在的问题
- ABA问题:不同线程修改值
比如线程1将值设置为A,然后线程2将值改为B后又改回A,那么此时若线程1进行CAS检查时发现得到的值与旧值是相同的,就会认为没有修改过,但实际上已经被其他线程修改过了
解决方法:添加版本号,用版本号比较 - 自旋问题:期待在不断重试的过程中获取锁
若一个线程或取锁,另一个线程不会阻塞,而是不断尝试是否能够获取锁。 与线程阻塞相比,自旋会浪费大量CPU资源
解决方法:自适应自旋