4、其他常考题目
4.经典常考题目
4.0 介绍一下CAS
CAS是一种无锁算法。有3个操作数:内存值V(也就是要更新的变量)、旧的预期值A、要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。
4.1 CAS的底层原理
CAS 全称为比较和交换,然后他的核心类是unsafe类,因为Java无法访问底层操作系统,所以借助unsafe来帮我们访问,相当于开了一个后门,他里面的方法可以直接操控内存,
public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);
CAS全称为Compare-And-Swap,它是一条CPU并发原语。
它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,因为原语必须是连续的,这个过程是原子的,不会造成数据不一致的情况。
4.2 wait和sleep关键字的不同
sleep使线程进行暂停一段时间,并不会释放锁,当时间到了之后,则会自动继续执行。
另外wait关键字也是使线程暂停,然后他会释放锁,需要其他线程使用 notify进行唤醒。
4.3 为什么wait()、notify()、notifyAll()被定义在Object类中而不是在Thread类中?
因为这些方法在操作同步线程时,都必须要标识他们操作线程的锁,只有同一个锁上的被等待线程,可以被同一个锁上的notify()
或notifyAll()
唤醒,不可以对不同锁中的线程进行唤醒,也就是说等待和唤醒必须是同一锁。而锁可以是任意对象,所以可以被任意对象调用的方法是定义在Object
类中。
如果把wait()
、notify()
、notifyAll()
定义在Thread类中,则会出现一些难以解决的问题,例如如何让一个线程可以持有多把锁?如何确定线程等待的是哪把锁?既然是当前线程去等待某个对象的锁,则应通过操作对象来实现而不是操作线程,而Object类是所有对象的父类,所以将这三种方法定义在Object类中最合适
4.4 线程安全的类有哪些?
通过synchronized 关键字给方法加上内置锁来实现线程安全
如:Timer,TimerTask,Vector,Stack,HashTable,StringBuffer
原子类Atomicxxx 包装类的线程安全类
如AtomicLong,AtomicInteger等等
ConcurrentHashMap,和 ConcurrentSkipListSet和ConcurrentSkipListMap等等。
推荐阅读:https://blog.csdn.net/dgeek/article/details/70145555
4.5 线程安全容器
HashTable,Vector,ConcurrentHashMap 等
