Thread

Java中的Thread的用法

同步队列与等待队列

  • 同步队列:所有尝试获取该对象Monitor失败的线程,都加入同步队列排队获取锁。调用了start、notify方法后会进入该队列。

  • 等待队列:已经拿到锁的线程在等待其他资源时,主动释放锁,置入该对象等待队列中,等待被唤醒,当调用notify会在等待队列中任意唤醒一个线程,
    将其置入同步队列的尾部,排队获取锁。调用wait方法时,会进入该队列。

Read More

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

Java中的异常

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