当前位置: 首页 >> 面试题 >> 技术 >> 后端开发 >> Java >>

Java多线程相关的面试要点

##synchronized和lock的区别

#用法的区别

synchronized:在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。

lock:需要显示指定起始位置和终止位置。一般使用ReentrantLock类做为锁,多个线程中必须要使用一个ReentrantLock类做为对象才能保证锁的生效。 且在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。

#性能区别

synchronized是托管给JVM执行的,而lock是java写的控制锁的代码。 synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。

而Lock用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就是CAS操作(Compare and Swap)。我们可以进一步研究ReentrantLock的源代码,会发现其中比较重要的获得锁的一个方法是compareAndSetState。这里其实就是调用的CPU提供的特殊指令。

#用途区别

synchronized原语和ReentrantLock在一般情况下没有什么区别,但是在非常复杂的同步应用中,请考虑使用ReentrantLock,特别是遇到下面2种需求的时候。

1.某个线程在等待一个锁的控制权的这段时间需要中断 2.需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程 3.具有公平锁功能,每个到来的线程都将排队等候

#ReentrantLock比synchronized多了三个高级功能:

1.等待可中断:在持有锁的线程长时间不释放锁的时候,等待的线程可以选择放弃等待。

2.公平锁:按照申请锁的顺序来获得锁。synchronized不是公平锁,ReentrantLock可以通过构造函数来实现公平锁。公平锁多建立一个队列。

3.绑定多个condition.通过多次new Condition可以获得多个Condition对象,可以简单的实现比较复杂的线程同步功能,通过await,signal.

##runnable和Thread 深层次

runnable实现线程可以对线程进行复用,因为runnable是轻量级的对象,重复new不会耗费太大资源,而Thread则不然,它是重量级对象,而且线程执行完就完了,无法再次利用

##volatile关键字

volatile用来修饰一个共享变量,实现该变量在多线程条件下可以透明访问,即线程使用该变量时每次都是从主存中获取。volatile可以保证变量的可见性,但是不能保证变量的原子性。

Loading