1、假如只有一个cpu,单核,多线程还有用吗
一般来说,一个任务既需要在CPU上花时间,也需要在IO上花时间,比如说读写文件等等。如果单核CPU、单线程的话,那么一个线程在处理的时候,CPU就是闲置的,这就浪费了CPU资源。而是多线程的话,一个CPU在等待IO的时候,另一个线程可以利用CPU进行计算,这样IO资源和CPU资源都得到了充分的利用。
2、sychronied修饰普通方法和静态方法的区别?什么是可见性
sychronied修饰普通方法时,锁是对象锁。
sychronied修饰静态方法时,锁是类锁,也就是类对应的class对象。每个类可以有不同的对象,但是class对象只有一个,所以如果不同的线程通过不同的对象调用方法不会造成线程阻塞,但是对于类锁而言,就算是不同的对象,多个线程调用该类的静态方法也会造成阻塞。
可见性是指:多个线程访问同一个变量时,其中一个线程修改了这个变量的值,其它线程能够立即看到修改值。volatile可以保证可见性,它会保证修改的值会立即更新到主存,所以对其它线程是可见的。而普通的共享变量不能保证可见性,因为被修改后放在线程的工作内存里,何时更新到主存不确定,所以其它线程读取的时候可能得到的是未修改的值。
3、锁分哪几类
(1)互斥锁和自旋锁
最基本的两种锁。互斥锁和自旋锁对于加锁失败之后的处理不一样。互斥锁加锁失败后,线程会释放CPU,给其他线程。自旋锁加锁失败后,线程会忙等待,直到它拿到锁。
(2)读写锁
读写锁适用于能明确区分读操作和写操作的场景。写锁是独占锁,因为任意时刻只能有一个线程持有写锁,而读锁是共享锁,多个线程可以同时持有。读写锁可以根据应用场景选择互斥锁和自旋锁的一种来实现。
(3)乐观锁与悲观锁
前面的互斥锁、自旋锁和读写锁都是悲观锁,悲观锁认为多线程同时修改共享资源的概率较高,很容易出现冲突,所以访问共享资源前就要上锁。乐观锁假定冲突的概率较低,所以她的工作方式是:先修改完共享资源,再验证这段时间有没有发生冲突,如果没有其它线程在修改资源,那么操作完成;如果发现有其它线程在修改,这次操作无效。
4、CAS无锁编程的原理
CAS即compare and swap(比较与交换),无锁编程也就是在不使用锁的情况下实现多线程之间的变量同步,其涉及到三个操作数:需要读写的内存值,预期值A,准备写入的新值B。工作原理是首先读取内存里的值V,和A进行比较,如果V=A,则将V更新为B,如果不相等,则操作就失败,进入自旋等待状态。
CAS是一种系统原语,是操作系统硬件提供的功能,也就是说比较与交换是一种原子操作,comapre成功了,swap也就成功了。
5、ReentrantLock和AQS实现原理
首先是ReentrantLock、AQS等几个关键类的关系。然后从ReentrantLock.lock()来分析ReentrantLock和AQS的原理,ReentrantLock.lock()的调用关系如下图:
先来看看最终的acquire方法,也就是