感谢牛客网网友提供的面试经验!
1. 解多线程环境下的线程安全体现在哪些方面?
答:多线程环境下的线程安全主要体现在原子性,可见性与有序性方面。
- 原子性是一组操作要么完全发生,要么没有发生,其余线程不会看到中间过程的存在。
- 可见性是指一个线程对共享变量的更新对于另外一个线程是否可见的问题。
- 有序性是指一个线程对共享变量的更新在其余线程看起来是按照什么顺序执行的问题。
2. 说一说自己对于 synchronized 关键字的了解?
synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized 关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。
同步:可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到返回的值或消息后才往下执行其他的命令。
异步:执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。
3. 谈一下你对 volatile 关键字的理解?
volatile关键字是一个轻量级的锁,可以保证可见性和有序性,但是不保证原子性。
- 保证了不同线程对该变量操作的内存可见性;
- 禁止指令重排序。
我们所写的代码,不一定是按照我们自己书写的顺序来执行的,编译器会做重排序,CPU 也会做重排序的,这样做是为了减少流水线阻塞,提高 CPU 的执行效率。这就需要有一定的顺序和规则来保证,不然程序员自己写的代码都不知道对不对了,所以有 happens-before 规则,其中有条就是 volatile 变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作、有序性实现的是通过插入内存屏障来保证的。
4. sleep() 和 wait() 的区别?
共同点:sleep和wait方法都可以使线程冻结,并释放cpu
区别:
- sleep()Thread类中的方法,wait()是Object类的方法。
- sleep()不释放对象锁,wait()放弃对象锁。
Sleep只是暂时停止执行线程任务,但并没有放弃cpu的使用权。而wait会放弃cpu使用权。重新进去就需要抢夺cpu。wait进入等待池,除非被唤醒,否则一直待在里面
- sleep()可以在任何地方使用,wait()只能在同步代码块中使用。
同步代码块:即有synchronized修饰符修饰的语句块,被该关键词修饰的语句块,将加上内置锁。实现同步。
例:synchronized(Object o ){}
5. 信号量
信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。
由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的:
- P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行
- V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1.
举个例子,就是两个进程共享信号量sv,一旦其中一个进程执行了P(sv)操作,它将得到信号量,并可以进入临界区,使sv减1。而第二个进程将被阻止进入临界区,因为当它试图执行P(sv)时,sv为0,它会被挂起以等待第一个进程离开临界区域并执行V(sv)释放信号量,这时第二个进程就可以恢复执行。
https://blog.csdn.net/wangcg123/article/details/79666424
https://www.zhihu.com/question/47411729