java 锁-java 对象锁
1.同步
在JDK 1.6之前,synchronized是一个重量级的锁,效率很低。
从JDK 1.6开始,synchronized做了很多优化,比如偏向锁、轻量级锁、自旋锁、自适应自旋锁、锁淘汰、锁粗化等技术,减少锁操作的开销。
一个synchronized同步锁包括四种状态:无锁、偏向锁、轻量级锁和重量级锁。 它将随着竞争逐步升级。 synchronized同步锁可以升级,不能降级。 目的是提高获取和释放锁的效率。
synchronized 同步修改代码块的底层原理
通过反编译.class文件,查看字节码,可以发现代码块中使用了monitorenter和monitorexit指令,其中monitorenter指令指向同步代码块的起始位置,monitorexit指令表示同步代码块的结束位置。
同步修改方法
您还可以查看字节码:ACC_SYNCHRONIZED 标志将包含在同步方法中。 该标记表明该方法是一个同步方法,从而执行相应的同步调用。
2.对象锁、类锁、私有锁
对象锁:使用synchronized修饰非静态方法,synchronized(this)同步代码块使用的锁是对象锁。
类锁:使用synchronized修饰静态方法,synchronized代码块使用的synchronized(类)锁就是类锁。
私有锁:在类内部声明一个私有属性如private Object lock,在需要加锁的同步块中使用synchronized(lock)
他们的特点:
私有锁实现的等待/通知机制:
Object lock = new Object();// 由等待方线程实现synchronized (lock) {
while (条件不满足) {
lock.wait();
} }// 由通知方线程实现synchronized (lock) {
条件发生改变
lock.notify(); }
3.可重入锁
ReentrantLock 是排他/独占锁。 与synchronized相比,更加灵活。 但是加锁和解锁的过程需要自己写。 它的灵活性在于它的许多特性。
ReentrantLock 需要显式释放锁。 特别是当程序出现异常时,synchronized会自动释放锁,而ReentrantLock不会自动释放锁,所以必须在finally中释放锁。
其特点:
ReentrantLock 是许多类的基础。 比如ConcurrentHashMap内部使用的Segment继承了ReentrantLock,CopyOnWriteArrayList也使用了ReentrantLock。
4. 可重入读写锁
之前写过一篇文章《ReentrantReadWriteLock读写锁及其在RxCache中的使用》java 锁,里面详细介绍了ReentrantReadWriteLock。
它有读锁(ReadLock)和写锁(WriteLock),读锁是共享锁,写锁是排它锁。
其特点:
5.中科院
上面提到的ReentrantLock和ReentrantReadWriteLock是基于AbstractQueuedSynchronizer(AQS)的,而AQS是基于CAS的。 CAS的全称是Compare And Swap(比较和交换),是一种无锁算法。
synchronized和Lock都是采用悲观锁的机制,而CAS是乐观锁的一种实现。
CAS的特点:
CAS 的问题:
6. 条件
Condition用于替代传统Object的wait()和notify()实现线程间的协作。
在Condition对象中,wait、notify、notifyAll对应的方法分别是await、signal、signalAll。
Condition 必须与 Lock 一起使用java 锁,并且 Condition 的实例必须绑定到 Lock。
其特点:
7.信号量
Semaphore、CountDownLatch、CyclicBarrier 都是并发工具类。
Semaphore可以指定多个线程同时访问一个资源,而synchronized和ReentrantLock都只允许一个线程一次访问一个资源。 由于Semaphore适合限制访问某些资源的线程数,所以可以用来节流。
Semaphore没有实现数据同步,数据同步仍然需要使用synchronized、Lock等实现。
其特点:
八。 倒数锁存器
CountDownLatch 可以被认为是一个倒计时计数器,它允许一个或多个线程等待其他线程完成操作。 因此,CountDownLatch 是一个共享锁。
CountDownLatch 的 countDown() 方法会将计数器减 1,而 await() 方法会阻塞当前线程,直到计数器变为 0。
在我的爬虫框架NetDiscovery中使用CountDownLatch来控制爬虫的挂起和恢复。
九。 锁的分类
十、总结
本文总结了Java中常用的一些锁及其一些特点。 掌握这些锁是掌握Java并发编程的基础。 当然,Java的锁不限于这些,比如ConcurrentHashMap的段锁(Segment),分布式环境下使用的分布式锁。