Java 锁基本概念 以及 Reentrantlock的特性

Java 锁中的基本概念

1. AQS – 指AbstractQueuedSynchronizer类。
AQS是java中管理“锁”的抽象类,锁的许多公共方法都是在这个类中实现。AQS是独占锁(例如,ReentrantLock)和共享锁(例如,Semaphore)的公共父类。

2. AQS锁的类别 – 分为“独占锁”和“共享锁”两种。
(01) 独占锁 – 锁在一个时间点只能被一个线程锁占有。根据锁的获取机制,它又划分为“公平锁”和“非公平锁”。公平锁,是按照通过CLH等待线程按照先来先得的规则,公平的获取锁;而非公平锁,则当线程要获取锁时,它会无视CLH等待队列而直接获取锁。独占锁的典型实例子是ReentrantLock,此外,ReentrantReadWriteLock.WriteLock也是独占锁。
(02) 共享锁 – 能被多个线程同时拥有,能被共享的锁。JUC包中的ReentrantReadWriteLock.ReadLock,CyclicBarrier, CountDownLatch和Semaphore都是共享锁。这些锁的用途和原理,在以后的章节再详细介绍。

3. CLH队列 – Craig, Landin, and Hagersten lock queue
CLH队列是AQS中“等待锁”的线程队列。 在多线程中,为了保护竞争资源不被多个线程同时操作而起来错误,我们常常需要通过锁来保护这些资源。在独占锁中,竞争资源在一个时间点只能被一个线程锁访问;而其它线程则需要等待。CLH就是管理这些“等待锁”的线程的队列。
CLH是一个非阻塞的 FIFO 队列。 也就是说往里面插入或移除一个节点的时候,在并发条件下不会阻塞,而是通过自旋锁和 CAS 保证节点插入和移除的原子性。

4. CAS函数 – Compare And Swap
CAS函数,是比较并交换函数,它是原子操作函数;即,通过CAS操作的数据都是以原子方式进行的。例如,compareAndSetHead(), compareAndSetTail(), compareAndSetNext()等函数。它们共同的特点是,这些函数所执行的动作是以原子的方式进行的。

5. Reentrantlock
在这里插入图片描述
6. synchronized和Reentrantlock
来聊一下他们两个的区别:
他们都是io阻塞锁,线程运行的时候,如果被另一个线程加锁,需要等另一个线程运行完,才能运行。
Synchronized会自己自动释放锁,Reentrantlock则需要自己手动释放锁,而且手动释放锁必须放在finally里面unlock,建议新手用前者。
Reentrantlock是可以公平,可以中断响应,限制等待时间。

7. 可重入锁与不可重入锁
重入锁实现可重入性原理或机制是:每一个锁关联一个线程持有者和计数器,当计数器为 0 时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法;当某一线程请求成功后,JVM会记下锁的持有线程,并且将计数器置为 1;此时其它线程请求该锁,则必须等待;而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增;当线程退出同步代码块时,计数器会递减,如果计数器为 0,则释放该锁。
synchronized为可重入锁,如下示例

public class TestDemo10 {
    public static synchronized void lock1(){
        System.out.println("lock1");
        lock2();
    }
    public static synchronized void lock2(){
        System.out.println("lock2");
    }
    public static void main(String[] args) {
        new Thread(){
            @Override
            public void run() {
                TestDemo10 lock = new TestDemo10();
                lock.lock1();
            }
        }.start();
        }
        }

输出

lock1
lock2

Reentrantlock为可重入锁,如下示例

        Lock lock = new ReentrantLock();
        int i = 0;
        try{
            lock.lock();
            i++;
            System.out.println(i);
            lock.lock();
            i++;
            System.out.println(i);
        } finally {
            lock.unlock();
            lock.unlock();
        }

输出

1
2

锁的可定时性

Thread thread1 = new Thread("thread1"){
            @Override
            public void run() {
                try{
                    if(fixtimelock.tryLock(5, TimeUnit.SECONDS)){
                        Thread.sleep(6000);
                        System.out.println(Thread.currentThread().getName()+"获取锁成功");
                    }else{
                        System.out.println(Thread.currentThread().getName()+"获取锁失败");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    fixtimelock.unlock();
                }
            }
        };
        Thread thread2 = new Thread("thread2"){
            @Override
            public void run() {
                try{
                    if(fixtimelock.tryLock(5, TimeUnit.SECONDS)){
                        Thread.sleep(6000);
                        System.out.println(Thread.currentThread().getName()+"获取锁成功");
                    }else{
                        System.out.println(Thread.currentThread().getName()+"获取锁失败");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    if(fixtimelock.isHeldByCurrentThread()){
                        fixtimelock.unlock();
                    }
                }
            }
        };
        thread1.start();
        thread2.start();

运行结果为:

thread2获取锁失败
thread1获取锁成功

因为线程1先获得锁,执行睡眠6秒的操作,睡眠中不会释放掉锁,因此线程2在5秒内没有获取到锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值