Java多线程并发编程 — 读写锁 Reentrant Read Write Lock
2017-06-26 14:35
453 查看
Java多线程并发编程 — 读写锁 Reentrant Read Write Lock
ReentrantReadWriteLock 实现 interface ReadWriteLock:
public interface ReadWriteLock {
/**
* Returns the lock used for reading.
*
* @return the lock used for reading
*/
Lock readLock();
/**
* Returns the lock used for writing.
*
* @return the lock used for writing
*/
Lock writeLock();
}
所以 ReentrantReadWriteLock 并非是真的一个“锁”,而是一个读锁和写锁的管理器,而真正实现锁功能的是 ReentrantReadWriteLock 的静态内部类 ReadLock 和 WriteLock。ReadLock 和 WriteLock 都是直接实现 interface Lock。
当多线程共享同一个数据源时,为了避免数据上的错乱,我们需要在读数据的时候防止写入操作,在写入的时候也不能进行读操作。怎么实现这一业务?synchronized、ReentrantLock 都可以实现,在读、写操作的方法都加上锁的保护,则可实现读写互斥。但这种做法会使并发大大折扣,例如在某一时间段只有大量读操作并没有写操作,但此时读操作也要进行排队,此时 ReentrantReadWriteLock 的价值就能发挥得淋漓尽致。
ReentrantReadWriteLock 的作用:支持同时多读,读的时候不能写,写的时候不能读。
看看具体的 DEMO1,一个支持多用户的银行账号(夫妻共用)的存款和查询的需求:
1,可多用户同时查询余额(读操作)
2,当有用户在查询余额时(读操作),该账号不能进行存取款操作(写入操作)
3,当有用户在存取款时(写入操作),该账号不能进行查询余额操作(读操作)
具体实现:
public class Test {
static class User {
int mID;
BankAccount mBankAccount;
public User(int ID, BankAccount bankAccount) {
mID = ID;
mBankAccount = bankAccount;
}
public void saveMoney(final int cash) {
new Thread(new Runnable() {
@Override
public void run() {
mBankAccount.saveMoney(mID, cash);
}
}).start();
}
public void checkBalance() {
new Thread(new Runnable() {
@Override
public void run() {
mBankAccount.checkBalance(mID);
}
}).start();
}
}
/**
* 支持多用户的银行账号(夫妻共用)
*/
static class BankAccount {
int mBalance;
ReentrantReadWriteLock mReentrantReadWriteLock = new ReentrantReadWriteLock();
ReentrantReadWriteLock.WriteLock mWriteLock = mReentrantReadWriteLock.writeLock();
ReentrantReadWriteLock.ReadLock mReadLock = mReentrantReadWriteLock.readLock();
public void saveMoney(int id, int cash) {
mWriteLock.lock();
try {
mBalance = mBalance + cash;
System.out.println(" 用户 " + id + " 正在进行存钱操作 ");
Thread.sleep(2000);
System.out.println(" 用户 " + id + " 存钱完成,存入 " + cash + " 元 ");
} catch (Exception e) {
e.printStackTrace();
} finally {
mWriteLock.unlock();
}
}
public void checkBalance(int id) {
mReadLock.lock();
try {
System.out.println(" 用户 " + id + " 正在进行查询余额操作 ");
Thread.sleep(2000);
System.out.println(" 余额:" + mBalance);
} catch (Exception e) {
e.printStackTrace();
} finally {
mReadLock.unlock();
}
}
}
public static void main(String[] var0) {
BankAccount bankAccount = new BankAccount();
User user1 = new User(1, bankAccount);
User user2 = new User(2, bankAccount);
user1.saveMoney(1000000);
// 同时查询余额
user1.checkBalance();
user2.checkBalance();
// 同时存款
user1.saveMoney(2000000);
user2.saveMoney(6000);
user1.checkBalance();
}
}
DEMO1 的输出:
用户 1 正在进行存钱操作
用户 1 存钱完成,存入 1000000 元
用户 1 正在进行查询余额操作
用户 2 正在进行查询余额操作
余额:1000000
余额:1000000
用户 1 正在进行存钱操作
用户 1 存钱完成,存入 2000000 元
用户 2 正在进行存钱操作
用户 2 存钱完成,存入 6000 元
用户 1 正在进行查询余额操作
余额:3006000
当两个用户同时查询余额时,可同时进行。
当两个用户同时存款时,不能同时进行,要进行队列排队。
可见,我们可以用 ReentrantReadWriteLock 进行一些读写需要互斥的一些业务上,特别适合在“大量读小量写”的业务,可以增大吞吐率。
相关文章推荐
- 13、java锁之读写锁ReentrantReadWriteLock.ReadLock与ReentrantReadWriteLock.WriteLock
- JAVA多线程之——读写锁 ReentrantReadWriteLock
- 《深入浅出 Java Concurrency》—锁机制(九) 读写锁 (ReentrantReadWriteLock) (2)
- 深入浅出 Java Concurrency (13): 锁机制 part 8 读写锁 (ReentrantReadWriteLock) (1)
- JAVA多线程之——读写锁 ReentrantReadWriteLock
- 《深入浅出 Java Concurrency》—锁机制(八) 读写锁 (ReentrantReadWriteLock) (1)
- java.util.concurrent.locks.ReentrantReadWriteLock读写锁源码解析
- JAVA多线程之——读写锁 ReentrantReadWriteLock
- JAVA多线程之——读写锁 ReentrantReadWriteLock
- java 读写锁 , 官方自带示例读解,ReentrantReadWriteLock
- 《深入浅出 Java Concurrency》—锁机制(九) 读写锁 (ReentrantReadWriteLock) (2)
- JAVA多线程之——读写锁 ReentrantReadWriteLock
- JAVA多线程之——读写锁 ReentrantReadWriteLock
- JAVA多线程之——读写锁 ReentrantReadWriteLock
- java多线程:并发包中ReentrantReadWriteLock读写锁的锁降级模板 写锁降级为读锁
- java 读写锁 , 官方自带示例读解,ReentrantReadWriteLock
- JAVA多线程之——读写锁 ReentrantReadWriteLock
- 深入浅出 Java Concurrency (14): 锁机制 part 9 读写锁 (ReentrantReadWriteLock) (2)
- 《深入浅出 Java Concurrency》—锁机制(八) 读写锁 (ReentrantReadWriteLock) (1)
- JAVA多线程之——读写锁 ReentrantReadWriteLock