使用多线程可能带来什么问题?
并发编程的目的就是为了能提高程序的执行效率提高程序运行速度,但是并发编程并不总是能提高程序运行速度的,而且并发编程可能会遇到很多问题,比如:内存泄漏、死锁、线程不安全等等
什么是线程死锁?
多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止
sleep()和wait()方法的区别与共同点
- 两者最主要的区别在于:sleep() 方法,线程不会释放对象锁,而 wait() 方法线程会释放对象锁线程不会释放对象锁 。
- 两者都可以暂停线程的执行。
wait()
通常被用于线程间交互/通信,sleep()
通常被用于暂停执行。wait()
方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的notify()
或者notifyAll()
方法。sleep()
方法执行完成后,线程会自动苏醒。或者可以使用wait(long timeout)
超时后线程会自动苏醒。
说一说自己对于 synchronized 关键字的了解
synchronized 关键字解决的是多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。
Synchronized 作用范围
- 修饰静态方法:作用于方法时,锁住的是对象的实例(this);
synchronized void method() {
//业务代码
}
-
修饰静态方法:当作用于静态方法时,锁住的是 Class 实例,又因为 Class 的相关数据存储在永久代 PermGen
(jdk1.8 则是 metaspace),永久带是全局共享的,因此静态方法锁相当于类的一个全局锁,
会锁所有调用该方法的线程;synchronized static void method() { //业务代码 }
-
**修饰代码块:**synchronized 作用于一个对象实例时,锁住的是所有以该对象为锁的代码块。它有多个队列,
当多个线程一起访问某个对象监视器的时候,对象监视器会将这些线程存储在不同的容器中synchronized(this) { //业务代码 }
ReentrantLock 与 synchronized的区别
-
相同点:
- 两者都为可重入锁 可重入锁 指的是自己可以再次获取自己的内部锁
-
不同点:
-
ReentrantLock 通过方法 lock()与 unlock()来进行加锁与解锁操作,与 synchronized 会
被 JVM 自动解锁机制不同,ReentrantLock 加锁后需要手动进行解锁。为了避免程序出
现异常而无法正常解锁的情况,使用 ReentrantLock 必须在 finally 控制块中进行解锁操
作。 -
ReentrantLock 相比 synchronized 的优势是可中断、公平锁、多个锁。这种情况下需要
使用 ReentrantLock -
synchronized 依赖于 JVM 而 ReentrantLock 依赖于 API
-
-
synchronized 关键字和 volatile 关键字的区别
- volatile 关键字是线程同步的轻量级实现,所以 volatile 性能肯定比synchronized关键字要好 。但是 volatile 关键字只能用于变量而 synchronized 关键字可以修饰方法以及代码块 。
- volatile 关键字能保证数据的可见性,但不能保证数据的原子性。synchronized 关键字两者都能保证。
- volatile关键字主要用于解决变量在多个线程之间的可见性,而 synchronized 关键字解决的是多个线程之间访问资源的同步性。