ReentranReadWriteLock读写锁

ReentranReadWriteLock读写锁

一些锁的概念

共享锁(S锁)又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S 锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。

排他锁(X锁)又称写锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。

  1. 读锁就是别人可以看,但是别人不能再修改

  2. 写锁就是别人既不能看,也不能修改

  3. 不论是写锁还是读锁都会造成死锁

当要对数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发。这种借助数据库锁机制,在修改数据之前先锁定,再修改的方式被称之为悲观并发控制

乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果冲突,则返回给用户异常信息,让用户决定如何去做。乐观锁适用于读多写少的场景,这样可以提高程序的吞吐量。

  1. 悲观锁上来就加锁
  2. 乐观锁只有再数据修改提交的时候才会检测,冲突就异常。

流程

public class RWLockDemo {
    public static void main(String[] args) throws InterruptedException {
        MyCatch myCatch = new MyCatch();

        for (int i = 0; i < 5; i++) {
            String key = String.valueOf(i);
            new Thread(()->{
                myCatch.put(key, UUID.randomUUID().toString().substring(0,8));
            },key).start();
        }

        TimeUnit.SECONDS.sleep(2);

        for (int i = 0; i < 5; i++) {
            String key = String.valueOf(i);
            new Thread(()->{
                myCatch.get(key);
            },key).start();
        }


    }
}

class MyCatch{

    private volatile Map<String,String> map = new HashMap<>();
    ReadWriteLock rwlock = new ReentrantReadWriteLock();

    public void put(String key,String value){
        rwlock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"\t准备写入数据");
            try {
                TimeUnit.MILLISECONDS.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            map.put(key,value);
            System.out.println(Thread.currentThread().getName()+"\t写入数据完成");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rwlock.writeLock().unlock();
        }
    }
    public String get(String key){
        rwlock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"\t准备读取数据");
            try {
                TimeUnit.MILLISECONDS.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            String va = map.get(key);
            System.out.println(Thread.currentThread().getName()+"\t读取数据完成");
            return va;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rwlock.readLock().unlock();
        }
        return null;
    }
}

与lock类似,无非是分类一下

上一篇:路由知识之ip route 命令中的疑惑


下一篇:2019年8月15日星期四(系统编程)