Java并发包:Lock和ReadWriteLock

来源:互联网 发布:海岛奇兵火箭升级数据 编辑:程序博客网 时间:2024/05/16 05:31

文章译自:http://tutorials.jenkov.com/java-util-concurrent/index.html
抽空翻译了一下这个教程的文章,后面会陆续放出,如有不妥,请批评指正。
转自请注明出处。

Lock

java.util.concurrent.locks.Lock是一种线程同步机制,类似于synchronized块。然而,Locks比同步代码块更灵活更复杂。

顺便提一下,我的另一篇文章Locks描述如何实现自定义的锁。

Java Lock Example

Lock是一个接口类,在应用程序中需要使用Lock的具体实现类,下面是一个简单的使用例子:

Lock lock = new ReentrantLock();lock.lock();//critical sectionlock.unlock();

首先,创建一个Lock对象,然后调用它的lock()方法。现在lock实例被锁住了。其它调用lock()方法的线程将会被阻塞住,直到锁上锁的线程调用unlock()方法。unlock()调用后,这时Lock就是打开的,其它的线程就可以锁住它。

Java Lock Implementations

Java.util.concurrent.locks包中对Lock接口的具体实现有下面这些:

  • ReentrantLock

Locks和Synchronized之间的不同:

  • Synchronized块不能确保线程进入临界区的顺序。
  • 你不能传递任何参数给Synchronized块,因此不能给synchronized块设置一个访问的超时时间。synchronized块必须完全包含在单个方法中。
  • Lock能够在分开的方法中分别调用lock()和unlock()方法。

Lock的一些方法

Lock接口主要有下面一些方法:
- lock()
- lockInterruptibly()
- tryLock()
- tryLock(long timeout, TimeUnit timeUnit)
- unlock()

Lock()方法在允许的情况下锁住Lock实例。如果Lock实例已经被锁住,调用lock()方法的线程将会被阻塞住,直到Lock释放锁。

lockInterruptibly()方法也会锁住Lock,除非调用了线程了interrupted方法。此外,如果一个线程正在通过该方法等待上锁,如果此时线程被中断,线程将退出这个方法的调用。

lockInterruptibly()允许在等待时由其他线程的Thread.interrupt()方法来中断等待线程而直接返回,这时是不用获取锁的,而会抛出一个InterruptException。而ReentrantLock.lock()方法则不允许Thread.interrupt()中断,即使检测到了Thread.interruptted一样会继续尝试获取锁,失败则继续休眠。只是在最后获取锁成功之后在把当前线程置为interrupted状态。

tryLock()方法尝试立即锁住Lock实例。如果锁成功会返回true,如果已经锁住了会返回false,这个方法不会被阻塞。

tryLock(long timeout, TimeUnit timeUnit)与trywork()相似,只是可以设置一个等待加锁的超时时间。

unlock() 方法解锁Lock实例。通常情况下,Lock的实现仅仅允许加锁的线程调用次方法,否则可能会导致非检查异常(RuntimeException)。

ReadWriteLock

Java.util.concurrent.locks.ReadWriteLock有一种高级的线程锁机制,它允许多个线程读某个资源,但每次只允许一个线程来写。
这种想法是,多个线程可以对共享的资源进行读操作,而且不会发生并发问题。并发问题发生在并发的读取和写入共享资源时或者是多个线程并发写入的情况。
这篇文仅涉及java内置的ReadWriterLock。如果你想了解更多关于ReadWriteLock背后实现的理论,你可以读读我另一篇文章Read Write Locks。

ReadWriteLock Locking规则

下面是一个线程允许锁住ReadWriteLock然后对保护的资源进行读或写操遵循的原则

  • Read Lock
    如果没有写入线程锁住ReadWriteLock,并且没有线程需要获得写入锁进行写入操作。那么多个线程可以获得锁来进行读操作。
  • Write Lock
    如果没有线程在写或者读操作,那么一次仅有一个线程可以获得锁以进行写操作。

ReadWriteLock的具体实现

ReadWriteLock是一个接口。Java.util.concurrent.locks包中包含以下对ReadWriteLock的具体实现。

  • ReentrantReadWriteLock

ReadWriteLock 示例

下面是一个简单的示例,展示如何创建一个ReadWriteLock以及如何锁住它来进行读和写操作:

ReadWriteLock readWriteLock = new ReentrantReadWriteLock();readWriteLock.readLock().lock();    // multiple readers can enter this section    // if not locked for writing, and not writers waiting    // to lock for writing.readWriteLock.readLock().unlock();readWriteLock.writeLock().lock();    // only one writer can enter this section,    // and only if no threads are currently reading.readWriteLock.writeLock().unlock();

注意,ReadWriteLock内部实际上包含两个Lock示例。一个保护读操作,另一个保护写操作。

1 0
原创粉丝点击