【多线程与并发篇之4个核心问题】
三、多线程与并发(4个)
1、解释下Java中的线程状态?
在Java中,线程具有五种状态。
这五种状态,是线程在其生命周期内,可能经历的不同阶段。
这五种状态分别是:
新建(NEW);
就绪(RUNNABLE);
阻塞(BLOCKED);
等待(WAITING)和超时等待(TIMED_WAITING);
终止(TERMINATED)。
1)新建(NEW)
当创建一个新的Thread对象时,该线程就处于新建状态。
它还没有开始执行,仅仅是作为一个对象存在。
2)就绪(RUNNABLE)
一旦线程对象,调用了start()方法,它就进入了就绪状态。
这意味着线程已经准备好执行,但是否真正执行,则取决于JVM的线程调度器。
3)阻塞(BLOCKED)
当线程试图获取一个内部的对象锁(而不是java.util.current.locks包中的锁)…
而该锁却被其他线程持有时,则该线程进入阻塞状态。
当持有锁的线程释放锁时,阻塞的线程将进入就绪状态。
4)等待和超时等待
等待(WAITING):
当线程调用了不带超时参数的Object.wait()方法、Thread.join()方法…
或者LockSupport.park()方法时,线程会进入等待状态。
等待状态中的线程,不会被分配CPU执行时间。
它们必须等待另一个线程,做出一些特定动作(例如通知)。
超时等待(TIMED_WAITING):
这是线程等待的另一个状态,但有一个指定的等待时间。
当线程调用了Thread.sleep(long millis)、Object.wait(long timeout)…
或Thread.join(long millis)等带有超时参数的方法时,线程会进入此状态。
5)终止(TERMINATED)
当线程执行完毕,或因为异常退出run()方法后,线程就进入了终止状态。
这个线程对象,将不再是可调度的,并且它的任务已经完成了。
以上就是线程的五种状态啦!
你若理解了这些线程状态,那么对于编写高效,且线程安全的Java代码非常重要。
例如,你需要知道…
何时可能需要等待,或通知其他线程。
何时可能需要处理阻塞状态,以及如何避免线程死锁等问题。
…
2、谈谈Java中的synized关键字和ReentrantLock的区别?
在Java中,synized关键字和ReentrantLock都是用于实现同步的重要机制。
两者有四个方面的区别。
即它们在“实现方式、使用灵活性、性能以及功能特性”这四个方面存在一些明显的区别。
1)实现方式:
synized是Java语言内置的关键字,它在JVM层面实现,无法被继承。
它提供了对类或者实例的加锁机制,使得同一时间,只有一个线程可以执行某段代码。
ReentrantLock是Java的一个类。
它是Java.util.current.locks包下提供的一个互斥锁,通过代码实现。
因此,它提供了比synized更丰富的功能。
例如,可以中断等待锁的线程,也可以尝试获取锁。
2)使用灵活性:
synized的使用较为简单,只需要在方法或代码块前,加上关键字即可。
但是,它的锁粒度较大,无法精细控制需要同步的代码范围。
而ReentrantLock,则提供了更多的控制选项,。
例如,可以通过lock()和unlock()方法,显式地获取和释放锁。
这使得开发者,可以更加灵活地控制同步代码的范围。
此外,ReentrantLock还支持公平锁和非公平锁,而synized总是非公平的。
3)性能:
在Java 6以及之后的版本中,synized和ReentrantLock的性能差距已经不大。
在某些情况下,ReentrantLock可能会比synized稍微快一些,因为它提供了更多的优化选项。
然而,这种差异通常是非常微小的,除非在特定的、高度竞争的环境中,否则很难观察到。
需要注意的是:
synized在发生异常时,会自动释放锁。
而ReentrantLock,则需要在finally块中显式地释放锁,否则可能导致死锁。
4)功能特性:
ReentrantLock提供了可中断的获取锁(loterruptibly())…
而synized是不支持这个功能的。
如果某个线程,在等待一个ReentrantLock…
那么其他线程,可以通过中断该等待线程,来使其放弃等待;
而synized,则做不到这一点。
ReentrantLock还提供了能够尝试获取锁的方法(tryLock())。
这个方法尝试获取锁,如果成功就返回true,否则立即返回false。
而synized,则无法做到。
综合以上四个方面的区别来说…
synized和ReentrantLock,都是Java中有效的同步工具,各有其优点和适用场景。
在选择使用哪种同步机制时,应根据具体的需求和上下文来决定。
对于简单的同步需求,synized可能是一个更好的选择…
因为它的使用更简单,且JVM会自动处理锁的获取和释放。
然而,对于更复杂的同步需求,或者需要更精细的控制同步范围的情况…
ReentrantLock,可能是一个更好的选择。
…
3、如何避免死锁?
避免死锁的方法有以下六点:
1)避免嵌套锁
尽量避免一个线程,在持有一个锁的同时,去请求另一个锁。
2)请求和释放锁的顺序
确保所有线程,以相同的顺序请求和释放锁。
3)使用定时锁
本章未完 点击下一页继续阅读