面试题之如何实现线程同步

2月 14, 2015 |

1)使用synchronized关键字

java中的每个对象都有一个monitor对象,当使用synchronized关键字来同步一段代码时,java提供monitorenter和monitorexit两个字节码指令来支持同步操作,
monitorenter的定义为:    每一个对象都关联一个monitor对象,线程执行monitorenter时获取该对象所关联的monitor的拥有权。如果另一个线程已经占有了该对象所关联的monitor,当前线程阻塞直到该对象被解锁,然后尝试获取拥有权。如果当前线程已经拥有该对象所关联的monitor,当前线程增加monitor的表示线程进入次数的计数器。如果该对象所关联的monitor没有被任何线程拥有,当前线程变成该monitor的拥有者,设置monitor的计数器(entry count)为1.
monitorexit的定义
当前线程必须为该对象的monitor的拥有者,将表示该线程进入monitor次数的计数器减1。如果计数器的值变为0,当前线程释放monitor。如果对象关联的monitor变为自由状态,其他等待的线程才能获取monitor。
作用于成员方法和static方法的synchronized分别锁住this对象和类的class对象。

2)使用java.util.concurrent.locks包中的方法来实现线程同步

这个包中的对象使用硬件的CAS(Compare-And-Swap)原子语义来实现同步。大致的行为是,如果该变量的值为期望的值时将其改为指定的值,否则(表示被并行的其他线程修改了)什么也不做。而这些操作是在direct memory中进行的而不是heap中,查看源代码会发现使用了sun.misc.Unsafe类来操作direct memory,这个类是没有公开的,但是网上有很多介绍使用这个类来实现高性能库的方法,可以搜一下啦。
这个包中主要有三个接口Condition,Lock,ReadWriteLock。 Lock锁的语义和synchronized一致,但是增加了非阻塞式加锁tryLock(),获取可以被中断的锁,以及timeout式地获取锁。
使用Lock的代码样例为:

ReadWriteLock管理一对Lock,分别进行读和写操作的加锁。便于实现读写同步。

Condition可以通过lock.newCondition()方法来获取,它拥有的方法有await(原子地释放拥有的锁然后挂起当前线程),signal,signalAll, 实现的语义如同Object.wait, Object.notify以及Object.notifyAll方法,但是通过Condition可以在一个对象上实现多套wait集(wait-sets)。在Condition的javadoc中演示了用其实现生产者-消费者模式的示例。

参考:

http://stackoverflow.com/questions/15684530/what-primitive-is-used-to-implement-the-synchronized-keyword

Posted in: 面试加油站

Comments are closed.