多线程相关锁,工具类

JUC结构

1.tools(工具类):又叫信号量三组工具类(三五六)

  • 1)CountDownLatch(闭锁) 是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待
  • 2)CyclicBarrier(栅栏) 之所以叫barrier,是因为是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 ,并且在释放等待线程后可以重用。
  • 3)Semaphore(信号量) 是一个计数信号量,它的本质是一个“共享锁“。信号量维护了一个信号量许可集。线程可以通过调用 acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。

2.executor(执行者):是Java里面线程池的顶级接口,但它只是一个执行线程的工具,真正的线程池接口是ExecutorService,里面包含的类有:

  • 1)ScheduledExecutorService 解决那些需要任务重复执行的问题
  • 2)ScheduledThreadPoolExecutor 周期性任务调度的类实现

3.atomic(原子性包):是JDK提供的一组原子操作类

包含有AtomicBoolean、AtomicInteger、AtomicIntegerArray等原子变量类,他们的实现原理大多是持有它们各自的对应的类型变量value,而且被volatile关键字修饰了。这样来保证每次一个线程要使用它都会拿到最新的值。

4.locks(锁包):是JDK提供的锁机制,相比synchronized关键字来进行同步锁,功能更加强大,它为锁提供了一个框架,该框架允许更灵活地使用锁包含的实现类有:(一四七)

  • 1)ReentrantLock 它是独占锁,是指只能被独自占领,即同一个时间点只能被一个线程锁获取到的锁。
  • 2)ReentrantReadWriteLock 它包括子类ReadLock和WriteLock。ReadLock是共享锁,而WriteLock是独占锁。
  • 3)LockSupport 它具备阻塞线程和解除阻塞线程的功能,并且不会引发死锁。

5.collections(集合类):主要是提供线程安全的集合, 比如:

1)ArrayList对应的高并发类是CopyOnWriteArrayList,

2)HashSet对应的高并发类是 CopyOnWriteArraySet,

3)HashMap对应的高并发类是ConcurrentHashMap等等

一、ReentrantLock重入锁

1.概述

完全可以替代synchronized关键字。灵活性更好。一个线程允许反复进入。如果一个线程多次获得锁,那么释放锁的时候,也必须释放相同次数。如果释放次数多,会有IllegalMonitorStateException异常。如果释放的次数少,相当于线程还有锁。默认是非公平锁。

lock():获得锁,如果锁被占用,则等待。

lockInterruptibly():获得锁,但优先响应中断。有中断不等待。

tryLock():尝试获得锁,如果成功,返回true();失败false。获得不到锁,则不进行等待,立刻返回。

tryLock(long time,TimeUnit unit):在给定的时间内尝试获得锁。

isHeldByCurrentThread():判断当前线程是否持有锁。

unLock():释放锁。

2.lockInterruptibly

synchronized要么获得锁,要么等待。重入锁可以被中断。即:如果一个线程正在等待锁,那么依然可以收到一个通知,被告知无需再等待,可以停止工作了。可以很好的应对死锁问题。

3.锁申请等待限时tryLock(long time,TimeUnit unit)

4.公平锁和非公平锁

大多数,锁的申请都是非公平锁。系统只是会从这个锁的等待线程中随机选择一个。

ReentrantLock r=new ReentrantLock(false);//非公平锁

5.AQS源码解析(见下一篇笔记)

二、Condition重入锁的搭配类

1.和Object方法的对比

Condition.await()->Object.wait()

Condition.signal()->Object.notify()

Condition.signalAll()->Objetct.notifyAll()

wait()notify()和Synchronized合作使用

await()signal()和ReentrantLock相关联

2.常用方法

void await使当前线程等待,并释放当前锁。

void awaitUninterruptibly与await()基本相同,不会在等待过程中响应中断。

long awaitNanos(long time)如果time时间内没有执行signal(),则解除等待状态。

boolean awaitUntill(Date deadline)在deadline时间内没有执行signal(),则解除等待状态。

boolean await(long time,TimeUnit unit)如果time时间内没有执行signal(),则解除等待状态。

void signal()唤醒一个等待中的线程。

void signalAll()唤醒所有等待中的线程。

三、Semaphore

信号量可以指定多个线程访问某一资源

构造函数:

  • public Semaphore(int permits); // permits:准⼊数
  • public Semaphore(int permits, boolean fair); // permits:准⼊数,fair:是否公平获得锁

主要方法:

  • public void acquire(); 尝试获得⼀个准⼊的许可。若⽆法获得,则线程会等待,直到有线程释放 ⼀个许可或者当前线程被中断。
  • public void acquireUninterruptibly(); 具有acquire⼀样的功能,但是不响应中断。
  • public void tryAcquire(); 尝试获得⼀个许可,如果成功就返回true,失败则返回false。
  • public void tryAcquire(long timeout, TimeUnit unit); 在指定时间内,尝试获得⼀个许可,如果成功 就返回true,失败则返回false。
  • public void release(); 资源访问结束后,释放⼀个许可

四、ReadWriteLock读写锁

1.5之后的读写分离锁,允许多个线程同时读,写写操作,读写操作需要持有锁。

ReadWriteLock.readLock(); ReadWriteLock.writeLock();

五、CountDownLatch闭锁

多线程控制工具,用来控制线程等待。设置需要countdown的数量num(构造函数传参),然后每一个线程执行完毕后,调用countDown(),主线程调用await()方法执行等待。直到num个子线程执行了countDown(),则主线程开始继续执行。一个子任务异常,不影响await()但异常需要体现出来。

六、CyclicBarrier循环栅栏

与CountDownLatch的区别是可以反复使用,CyclicBarrier可以接收一个参数作为Runnable barrierAction。每当计数器一次计数完成后CyclicBarrier.await()时,系统会执行Runnable barrierAction里的动作。

CyclicBarrier.await()会抛出两种异常,InterruptedException中断异常,BrokenBarrierException CyclicBarrier破损异常系统不需要再等待了。

七、LockSupport线程阻塞工具类

  • 线程阻塞工具,可以在线程内任意位置让线程阻塞。
  • 和Thread.suspend()相比,弥补了resume()在前边发生导致线程无法继续执行的情况。
  • 和Object.wait()相比,不需要先获得某个对象的锁,也不会抛出InterruptedException。

park()和unpark()

unpark()要传一个调用park()的线程

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值