Java中的异常

Java语言是编译型语言,Java代码编译成字节码,然后由JVM解释成目标代码由CPU执行;这里包含我们常说的两个过程,即编译时和运行时;
Java语言把编译时可能产生的异常称为受检查异常,把运行时可能产生的异常称为不受检查异常(比如NullPointException和ClassNotFoundException)。

CAS原理

CAS原理

在计算机科学中,比较和交换(Conmpare And Swap)是用于实现多线程同步的原子指令。 它将内存位置的内容与给定值进行比较,只有在相同的情况下,
将该内存位置的内容修改 为新的给定值。 这是作为单个原子操作完成的。 原子性保证新值基于最新信息计算; 如果 该值在同一时间被另一个线程更新,则写入将失败。
操作结果必须说明是否进行替换; 这 可以通过一个简单的布尔响应(这个变体通常称为比较和设置),或通过返回从内存位置读取的值来完成。

CAS带来的问题

多线程情况下,每个线程使用 CAS 操作欲将数据 A 修改成 B,当然我们只希望 只有一个线程能够正确的修改数据,并且只修改一次。当并发的时候,其中一个
线程已经将 A 成功的改成了 B,但是在线程并发调度过程中尚未被调度,在这个期间,另外一个线程(不在并发中的请求线程)将 B 又修改成了 A,
那么原来并发中的线程又可以通过 CAS 操作将 A 改成 B。

解决办法

java 中提供了 AtomicStampedReference 来解决这个问题,它是基于版本或者是 一种状态,在修改的过程中不仅对比值,也同时会对比版本号

Java锁

锁的基本概念

从广义上来定义:

悲观锁: 比如线程A对某个变量进行修改,在这个修改期间,它持悲观心理,认为其他线程在这个期间,也有可能去修改这个变量,所以它就给变量加个锁,保证在它修改期间,别的线程没法去访问这个变量。这个锁就是悲观锁。
悲观锁是重量级锁,代表对象synchronized和Lock。悲观锁适合写操作多的场景,先加锁可以保证写操作时数据正确。

乐观锁: 比如线程A对某个变量进行修改,在这个修改期间,它持乐观心理,认为其他线程在这个期间,不会去修改这个变量,所以不会加锁。 只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,
当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的操作(例如报错或者自动重试)。乐观锁是轻量级锁,代表对象CAS。Java原子类中的递增操作就通过CAS自旋实现的。
乐观锁适合读操作多的场景,不加锁的特点能够使其读操作的性能大幅提升。

Read More