读写锁总结

1. ReadWriteLock
对象的方法中一旦加入了synchronized关键字,则任何时刻只能有一个线程访问synchronized修饰的块。假设有个数据对象用户拥有写方法和读方法,那么多线程环境下要保证数据的安全,需要对该对象的读、写方法都加synchronized关键字。 这样,
    1)对于任何线程在写入时,其他线程都无法读,也无法写;
    2)如果有线程在读时,其他线程也无法读,也无法写。
这样的规则,对于写入操作时,没有问题。但对于读操作时,会造成不必要的性能瓶颈。因为读操作是可以多线程同时进行的,而synchronized限制了数据的并发读。

ReadWriteLock解决了这个问题:
    1)当写操作时,其他线程无法读,也无法写
    2)当读操作时,其他线程可以读,但无法写。


2. ReentrantReadWriteLock

1) 可重入概念

若一个程序或子程序可以“安全的被并行执行(Parallel computing)”,则称其为可重入(reentrant或re-entrant)的。即当该子程序正在运行时,可以再次进入并执行它(并行执行时,个别的执行结果,都符合设计时的预期)。可重入概念是在单线程操作系统的时代提出的。

3. 互斥锁:
所谓互斥锁,只指一次最多只能有一个线程持有的锁。在jdk1.5之前,只能用synchronized控制多线程对共享资源的访问。现在Lock提供了比synchronized更强大的锁定操作。

Lock与synchronized的主要区别:
    -- synchronized机制提供了对与每个对象相关的隐式的监视器锁,并强制所有锁的获取和释放都必须在同一个块结构中。当获取了多个锁时,他们必须以相反的顺序释放。即synchronized对于锁的释放是隐式的。
    -- 而Lock机制必须显式的调用Lock对象的unlock()方法,这样,获取锁和释放锁可以不在同一个块中,这样可以以更自由的顺序释放锁。

ReentrantLock比Synchronized强大在哪?
1)ReentrantLock可以实现fair lock (所谓fair lock就是获得锁的顺序和申请锁的时间的顺序是一致的 )
public ReentrantLock(boolean fair) {
    sync = (fair) ? new FairSync() : new NonfairSync();
}

2) ReentrantLock支持中断处理
public final void acquireInterruptibly(int arg) throws InterruptedException {
    if (Thread.interrupted()) {
        throw new InterruptedException();
    }
    if (!tryAcquire(arg)) {
        doAcquireInterruptibly(arg);
    }
}

3) ReentrantLock可以和condition结合使用
public boolean hasWaiters(Condition condition) {
    if (condition == null) {
        throw new NullPointerException();
    }
    if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) {
        throw new IllegalArgumentException("not owner");
    }
    return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
}










猜你喜欢

转载自doudou-001.iteye.com/blog/2284751