juc哪些锁是悲观锁?该怎么实现?

TheDisguiser 2020-06-15 22:42:31 java常见问答 6328

在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类图如下:

juc哪些锁是悲观锁

5)、ReentrantReadWriteLock

ReentrantReadWriteLock是读写锁,它也是接口ReadWriteLock的实现类,它包括子类ReadLock和WriteLock。ReentrantLock是共享锁,而WriteLock是独占锁。

UML类图如下:

juc哪些锁是悲观锁

6)、Semaphore

Semaphore是一个计数信号量,它的本质可以说是是一个"共享锁"。

信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程就能获取该许可;否则线程就必须等待,一直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。

UML类图如下:

juc哪些锁是悲观锁

二、悲观锁该如何实现?

示例:

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工具网吧。

推荐阅读:

AQS,juc下的类有哪些?有什么作用?

悲观锁的代码实现如何编写?

悲观锁提供缓存功能需要怎么处理?悲观锁是什么?