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对象。
这个包中的对象使用硬件的CAS(Compare-And-Swap)原子语义来实现同步。大致的行为是,如果该变量的值为期望的值时将其改为指定的值,否则(表示被并行的其他线程修改了)什么也不做。而这些操作是在direct memory中进行的而不是heap中,查看源代码会发现使用了sun.misc.Unsafe类来操作direct memory,这个类是没有公开的,但是网上有很多介绍使用这个类来实现高性能库的方法,可以搜一下啦。
这个包中主要有三个接口Condition,Lock,ReadWriteLock。 Lock锁的语义和synchronized一致,但是增加了非阻塞式加锁tryLock(),获取可以被中断的锁,以及timeout式地获取锁。
使用Lock的代码样例为:
1 2 3 4 5 6 7 |
Lock l = new ReentrantLock(); l.lock(); try { // access the resource protected by this lock } finally { l.unlock(); } |
ReadWriteLock管理一对Lock,分别进行读和写操作的加锁。便于实现读写同步。
Condition可以通过lock.newCondition()方法来获取,它拥有的方法有await(原子地释放拥有的锁然后挂起当前线程),signal,signalAll, 实现的语义如同Object.wait, Object.notify以及Object.notifyAll方法,但是通过Condition可以在一个对象上实现多套wait集(wait-sets)。在Condition的javadoc中演示了用其实现生产者-消费者模式的示例。
Posted in: 面试加油站
Comments are closed.