在java中有个juc类,这个类包含了很多锁机制,小伙伴们知道哪些是悲观锁吗?它要怎么实现呢?快听小编与你说说吧。
一、juc哪些是悲观锁?
首先我们来粗略了解一下,JUC中的锁包括了:Lock接 口,ReadWriteLock接口,LockSupport阻塞原语,Condition条 件,ReentrantLock独占 锁,ReentrantReadWriteLock读写锁。因为CountDownLatch,CyclicBarrier与Semaphore也是通过 AQS来实现的,所以,这次我们也将它们归纳到锁的框架中来进行介绍。其实对比同步锁来说,JUC中的锁,功能会更加强大,因为它为锁提供了一个框架,这个框架会允许它更灵活地使用锁,就是使用上会变得更加艰难。
我们可以先来了解一下锁的框架图,如下:
1)、 Lock
它是可重入锁,JUC包中 Lock 接口是支持那些语义不同的锁规则的。其实所谓语义不同,是指一个锁它可以是有"公平机制的锁"、"非公平机制的锁"、"可重入的锁"等等。"公平机制"是 指"不同线程获取锁的机制是公平的",然"非公平机制"则是指"不同线程获取锁的机制是非公平的","可重入的锁"是指同一个锁能够被一个线程多次获取。
2)、ReadWriteLock
ReadWriteLock 是读写锁,它以类似与lock的方式定义了一些读取者可以共享而写入者独占的锁。在JUC包中只有一个类实现了该接口,即 ReentrantReadWriteLock,因为它适用于大部分的标准用法上下文。但
3)、LockSupport
LockSupport是具有许可证的锁,它会提供“创建锁”和“其他同步类的基本线程阻塞原语”。
LockSupport的功能与"Thread中的Thread.suspend()和Thread.resume()比较相似",LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程。
4) 、ReentrantLock
ReentrantLock是独占锁。独占锁,就是指只能被独自占领,即同在某一时间点只能被一个线程锁获取到的锁。ReentrantLock锁中包括"公平的ReentrantLock"和"非公平的ReentrantLock"。"公平的ReentrantLock"是指"不同线程获取锁的机制是 公平的",而"非公平的 ReentrantLock"则是指"不同线程获取锁的机制是非公平的",ReentrantLock是"可重入的锁"。
UML类图如下:
5)、ReentrantReadWriteLock
ReentrantReadWriteLock是读写锁,它也是接口ReadWriteLock的实现类,它包括子类ReadLock和WriteLock。ReentrantLock是共享锁,而WriteLock是独占锁。
UML类图如下:
6)、Semaphore
Semaphore是一个计数信号量,它的本质可以说是是一个"共享锁"。
信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程就能获取该许可;否则线程就必须等待,一直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。
UML类图如下:
二、悲观锁该如何实现?
示例:
pojo类
class ProductStock { private Long productId; //商品id private Integer number; //库存量 public Long getProductId() { return productId; } public void setProductId(Long productId) { this.productId = productId; } public Integer getNumber() { return number; } public void setNumber(Integer number) { this.number = number; } }
具体实现类
/** * 更新库存(使用悲观锁) * @param productId * @return */ public boolean updateStock(Long productId) { //先锁定商品库存记录 ProductStock product = query("SELECT * FROM tb_product_stock WHERE product_id=#{productId} FOR UPDATE", productId); if (product.getNumber() > 0) { int updateCnt = update("UPDATE tb_product_stock SET number=number-1 WHERE product_id=#{productId}", productId); if (updateCnt > 0) { //更新库存成功 return true; } } return false; }
以上就是今天的所有内容了,如果小伙伴们还想了解更多java入门知识,就请持续关注奇Q工具网吧。
推荐阅读: