快速鸟瞰并发编程,-呕心沥血整理的架构技术【1】

synchronized关键字用于防止不同的线程同时执行相同的代码块, 其实就是指这个代码块只被一个线程执行。当线程A获得synchronized锁后,只有线程A访问synchronized代码块,是一种独占式模式操作, 例如: 13号技师被王根基同学带进屋后,王根基同学在门上挂了把锁, 其它线程得等待, 保证了13号技师只能与王根基(线程)进行业务操作 ,不难看出这个操作原子操作(只有王根基线程操作13号技师)。此外,它保证其它线程在获取相同的锁之后将观察正在操作线程的结果,何时释放锁。

class JamesAtomicOperation {
private int counter0 ;
private int counter1 ;
void increment(){
synchronized(this){
counter0 ++ ;
counter1 ++ ;
}
}
}

synchronized关键字可以在方法级来指定。

锁是可重入的,因此如果线程已经拥有锁,可以再次成功获取它。

class JamesReentrantcy {
synchronized void doAll(){
doFirst();
doSecond();
}
synchronized void doFirst(){
System.out.println(“第一次操作成功。”);
}
synchronized void doSecond(){
System.out.println(“第二次操作成功。”);
}
}

等待/通知

wait/notify/notifyAll方法在 Object类中声明。wait的作用可以使线程状态变成 WAITINGTIMED_WAITING(如果已等待超时)状态。为了唤醒一个线程,可以执行以下任何操作:

  • 另一个线程调用 notify,唤醒在监视器上等待的任意线程。

  • 另一个线程调用 notifyAll,唤醒监视器上等待的所有线程。

  • 如果调用 Thread#interrupt。在这种情况下,会抛出 InterruptedException

最常见的模式是条件循环:

class JamesConditionLoop {
private Boolean condition;
synchronized void waitForCondition()throws InterruptedException {
while(!condition){
wait();
}
}
synchronized void satisfCondition(){
condition = true ;
notifyAll();
}
}

  • 同志们请记住,如果 wait/notify/notifyAll要在你的对象上使用,需要首先获取此对象锁。

  • 总是在一个循环中等待检查正在等待的条件 - 如果另一个线程在等待开始之前满足条件,这就解决了时间问题。此外,它还可以保护您的代码免受可能(并且确实发生)的虚假唤醒。

  • 在打电话之前,请务必确保您满足等待条件 notify/notifyAll。如果不这样做将导致通知,但没有线程能够逃脱其等待循环。

volatile关键字

volatile解决了多线程之间的资源可见性问题,有这么一层关系大家需要知道:对某个volatile字段的写操作happens-before后续对同一个volatile字段的读操作,比如线程1写入了volatile变量v(这里和后续的“变量”都指的是对象的字段、类字段和数组元素),接着线程2读取了v,那么,线程1写入v及之前的写操作都对线程2可见(线程1和线程2可以是同一个线程)。因此,它保证字段的任何后续读取都将看到由最近写入设置的值。

class JamesVolatileFlag implements Runnable {
private volatile Boolean shouldStop;
public void run() {
while (!shouldStop) {
// TODO业务代码
}
System.out.println(“停止.”);
}
void stop() {
shouldStop = true;
}
public static void main(String[] args) throws InterruptedException {
JamesVolatileFlag flag = new JamesVolatileFlag();
Thread thread = new Thread(flag);
thread.start();
flag.stop();
thread.join();
}
}

原子操作

java.util.concurrent.atomic包路径下的一些类以无锁方式支持单个值上的原子复合操作,类似于volatile。

使用AtomicXXX类,可以实现原子 check-then-act操作:

class JamesCheckThenAct {
private final AtomicReference value = new AtomicReference<>();
void initialize() {
if (value.compareAndSet(null, “value”)) {
System.out.println(“仅初始化一次.”);
}
}
}

jdk8中新增的 AtomicIntegerAtomicLong具有 increment/decrement(自增自减)的原子操作:

class JamesIncrement {
private final AtomicInteger state = new AtomicInteger();
void advance() {
int oldState = state.getAndIncrement();
System.out.println(“Advanced: '” + oldState + “’ -> '” + (oldState + 1) + “'.”);
}
}

若计数器不需要原子操作来获取其值,请考虑使用 LongAdder而不是 AtomicLong/ AtomicInteger类。LongAdder其实就是把一个变量分解为多个变量,让同样多的线程去竞争多个资源,性能问题就可以解决了,因此它在高争用下表现更好。

ThreadLocal

从概念上讲,ThreadLocal就好像在每个Thread中都有一个具有自己版本的变量。ThreadLocal通常用于存储每个线程的值,如“当前事务”或其他资源。此外,它们还用于维护每线程计数器,统计信息或ID生成器。

class JamesTransactionManager {
private final ThreadLocal currentTransaction = ThreadLocal.withInitial(NullTransaction::new);
Transaction currentTransaction() {
Transaction current = currentTransaction.get();
if (current.isNull()) {
current = new TransactionImpl();
currentTransaction.set(current);
}
return current;
}
}

好了, 第1篇就到这里,希望大家持续关注更新…………

最后

一次偶然,从朋友那里得到一份“java高分面试指南”,里面涵盖了25个分类的面试题以及详细的解析:JavaOOP、Java集合/泛型、Java中的IO与NIO、Java反射、Java序列化、Java注解、多线程&并发、JVM、Mysql、Redis、Memcached、MongoDB、Spring、Spring Boot、Spring Cloud、RabbitMQ、Dubbo 、MyBatis 、ZooKeeper 、数据结构、算法、Elasticsearch 、Kafka 、微服务、Linux。

这不,马上就要到招聘季了,很多朋友又开始准备“金三银四”的春招啦,那我想这份“java高分面试指南”应该起到不小的作用,所以今天想给大家分享一下。

image

请注意:关于这份“java高分面试指南”,每一个方向专题(25个)的题目这里几乎都会列举,在不看答案的情况下,大家可以自行测试一下水平 且由于篇幅原因,这边无法展示所有完整的答案解析

起到不小的作用,所以今天想给大家分享一下。

[外链图片转存中…(img-ENzm5MrB-1714701770113)]

请注意:关于这份“java高分面试指南”,每一个方向专题(25个)的题目这里几乎都会列举,在不看答案的情况下,大家可以自行测试一下水平 且由于篇幅原因,这边无法展示所有完整的答案解析

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值