标签:content jdk cpu 时间 才有 代码 its ant 队列
Java中的锁主要用于保障多并发线程情况下数据的一致性。
在多线程编程中为了保障数据的一致性,通常需要在使用对象或者方法之前加锁,这时如果有其他线程也需要使用该对象或方法。则首先要获得锁,如果某个线程发现锁正在被其他线程使用,就会进入阻塞队列等待锁的释放,直到其他线程执行完成并释放锁,该线程才有机会再次获取锁进行操作。
乐观锁采用乐观的思想处理数据,在每次读取数据时都认为别人不会修改该数据,所以不会上锁,但在更新时会判断在此期间别人有没有更新该数据。
通常采用在写时先读出当前版本号然后加锁的方法。具体过程为:比较当前版本号与上次的版本号,如果版本号一致,则更新,如果不一致,则重复进行读、比较、写操作。
Java中的乐观锁是通过CAS(比较和交换)操作实现的。
CAS是一种原子更新操作,在对数据操作之前会比较当前值跟传入的值是否一样,如果一样则更新,否则不执行更新操作,直接返回失败状态。
悲观锁采用悲观思想处理数据,在每次读取数据时都认为别人会修改数据,所以每次在读取数据时都会上锁,别的线程想读写数据时就会阻塞、等待直到拿到锁。
Java中的悲观锁大部分基于AQS(抽象的队列同步器)架构实现。该框架下的锁会先尝试以CAS乐观锁去获取锁,如果获取不到,则会转为悲观锁。许多同步类的实现都依赖于AQS,例如Synchronized、ReentrantLock、CountDownLatch、Semaphore等。
如果持有锁的线程能在很短的时间内释放锁的资源,那么那些等待竞争锁的线程就不需要做内核态和用户态的切换进入阻塞、挂起状态,只需要等一等(自旋),等待持有锁的线程释放锁后即可获得锁,避免了用户线程在内核状态的切换上导致的锁时间消耗。
JDK不同的版本所采用的自旋周期不同,JDK1.5为固定的时间,JDK1.6引入适应性自旋锁(不再是固定值)。适应性自旋锁的自旋时间是由上一次在同一个锁上的自旋时间及锁的拥有着的状态来决定的。一般为一个线程上下文切换的时间。
synchronized关键字用于Java 对象、方法、代码块提供线程安全的操作。synchronized属于独占锁、悲观锁、可重入锁。
在使用synchronized修饰对象时,同一时刻只能有一个线程对该对象进行访问;在synchronized修饰方法、代码块时,同一时刻只能有一个线程执行该方法或代码块,其他线程只有等待当前线程执行完毕并释放锁资源后才能访问该对象或执行代码块。
synchronized内部包含6个区域:ContentionList、EntryList、WaitSet、OnDeck、Owner、!Owner。
标签:content jdk cpu 时间 才有 代码 its ant 队列
原文地址:https://www.cnblogs.com/strong-FE/p/12398840.html