L7:Java并发2

1. Java 并发包(*JUC)
2. 到底什么是锁
3. 并发原子类*
4. 并发工具类详解*
5.7 课总结回顾与作业实践

一 Java并发包

JDK核心库的包有哪些?

java.lang.* 最基础,Integer/String
java.io.* IO读写,文件操作
java.util.* 工具类,集合/日期
java.math.*
java.net.*
java.rmi.* Java内置的远程调用
java.sql.*
javax.* Java拓展API
sun.* sun的JDK拓展

JUC包内容分类
在这里插入图片描述
在这里插入图片描述

二 锁是什么

为什么需要显式的Lock / synchronized方式加锁有什么问题?

1、同步块的阻塞无法中断(不能 Interruptibly2、同步块的阻塞无法控制超时(无法自动解锁)
3、同步块无法异步处理锁(即不能立即知道是否可以拿到锁)
4、同步块无法根据条件灵活的加锁解锁(即只能跟同步块范围一致)

Lock锁

  1. 使用方式灵活可控
  2. 性能开销小
  3. 锁工具包: java.util.concurrent.locks
Lock 接口设计:
// 1.支持中断的 API
void lockInterruptibly() throws InterruptedException;
// 2.支持超时的 API
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
// 3.支持非阻塞获取锁的 API
boolean tryLock();

基础接口:
//获取锁; 类比 synchronized (lock)
void lock(); 
//获取锁; 允许打断;
void lockInterruptibly()
throws InterruptedException; 
//尝试获取锁; 成功则返回 true; 超时则退出
boolean tryLock(long time, TimeUnit unit)
throws InterruptedException; 
//尝试【无等待】获取锁; 成功则返回 true
boolean tryLock();
//解锁;要求当前线程已获得锁; 类比同步块结束
void unlock(); 
 //新增一个绑定到当前Lock的条件;
Condition newCondition();
示例: (类比: Object monitor)
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
public class LockCounter {
	private int sum = 0;
	// 可重入锁+公平锁
	private Lock lock = new ReentrantLock(true);
	public int addAndGet() {
		try {
			lock.lock();
			return ++sum;
		} finally {
			lock.unlock();
		}
	}
	public int getSum() {
		return sum;
	}
}

读写锁

注意:ReadWriteLock 管理一组锁,一个读锁,一个写锁。
读锁可以在没有写锁的时候被多个线程同时持有,写锁是独占的。
所有读写锁的实现必须确保写操作对读操作的内存影响。每次只能有一个写线程,但是同时可以有多个线程并发地读数据。ReadWriteLock 适用于读多写少的并发情况

// 构造方法
public ReentrantReadWriteLock(boolean fair) {
	sync = fair ? new FairSync() : new NonfairSync();
	readerLock = new ReadLock(this);
	writerLock = new WriteLock(this);
}

public class ReadWriteLockCounter {
	private int sum = 0;
	// 可重入-读写锁-公平锁
	private ReadWriteLock lock = new ReentrantReadWriteLock(true);
	public int incrAndGet() {
		try {
			lock.writeLock().lock(); // 写锁; 独占锁; 被读锁排斥
			return ++sum;
		} finally {
			lock.writeLock().unlock();
		} }
	public int getSum() {
		try {
			lock.readLock().lock(); // 读锁; //共享锁; 保证可见性
			return ++sum;
		} finally {
			lock.readLock().unlock();
		}
	}
}

基础接口Condition

通过 Lock.newCondition()创建。
可以看做是 Lock 对象上的信号。类似于 wait/notify

三个用锁的最佳实践

  1. 永远只在更新对象的成员变量时加锁
  2. 永远只在访问可变的成员变量时加锁
  3. 永远不在调用其他对象的方法时加锁

最小使用锁:

  1. 降低锁范围
  2. 细分锁粒度

三 并发原子类

Atomic工具类

无锁技术底层实现原理:

  • Unsafe API -> Compare-And-Swap
  • CAS指令

CAS 本质上没有使用锁。
并发压力跟锁性能的关系:
1、压力非常小,性能本身要求就不高;
2、压力一般的情况下,无锁更快,大部分都一次写入;
3、压力非常大时,自旋导致重试过多,资源消耗很大

LongAdder对AtomicLong的改进

分段思想,类似于归并思想

四 并发工具类详解

工具类底层原理 AQS(AbstractQueuedSynchronizer,抽象队列同步器)

在这里插入图片描述

Semaphore - 信号量

  1. 准入数量 N
  2. N =1 则等价于独占锁
public class SemaphoreCounter {
	private int sum = 0;
	private Semaphore readSemaphore = new Semaphore(100, true);
	private Semaphore writeSemaphore = new Semaphore(1);
	public int incrAndGet() {
		try {
			writeSemaphore.acquireUninterruptibly();
			return ++sum;
		} finally {
			writeSemaphore.release();
		}
	}
	public int getSum() {
		try {
			readSemaphore.acquireUninterruptibly();
			return sum;
		} finally {
			readSemaphore.release();
		}
	}
}

CountdownLatch

在这里插入图片描述

public static class CountDownLatchTask implements Runnable {
	private CountDownLatch latch;
	public CountDownLatchTask(CountDownLatch latch) {
		this.latch = latch;
	}
	@Override
	public void run() {
		Integer millis = new Random().nextInt(10000);
		try {
			TimeUnit.MILLISECONDS.sleep(millis);
			this.latch.countDown();
			System.out.println(“我的任务OK了:"+Thread.currentThread().getName());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

// 使用示例
public static void main(String[] args) throws Exception {
	int num = 100;
	CountDownLatch latch = new CountDownLatch(num);
	List<CompletableFuture> list = new ArrayList<>(num);
	for (int i = 0; i < num; i++) {
		CompletableFuture<Void> future = CompletableFuture.runAsync(new CountDownLatchTask(latch));
		list.add(future);
	}
	latch.await();
	for (CompletableFuture future : list) {
		future.get();
	}
}

CyclicBarrier

场景: 任务执行到一定阶段, 等待其他任务对齐
在这里插入图片描述
在这里插入图片描述

Future/FutureTask/CompletableFuture

在这里插入图片描述

总结

Java 并发包
什么是锁
并发原子类
并发工具类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wimb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值