Java JUC并发之读写锁

九、读写锁 ReadWriteLock

Read Lock 读锁 (共享锁)=> 允许多个线程一起读 读的时候不允许写操作

Write Lock 写锁 (独占锁)=> 只允许一个线程(独家)写的时候不允许读操作

读写锁的目的: 保证线程安全 读写分离

package com.liu.rw;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 独占锁(排他锁) 写锁 一次只能被一个线程占有
 * 共享锁 读锁 多个线程同时占有
 * ReadWriteLock 读写锁
 * 读-读 可以共存!
 * 读-写 不能共存 读写分离
 * 写-写 不能共存
 */
public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCacheLock myCache = new MyCacheLock();

        // 写入操作
        for (int i = 1; i <= 10; i++) {
            final String temp = String.valueOf(i);

            new Thread(()->{
                myCache.put(temp,temp);
            },String.valueOf(i)).start();
        }


        // 读取操作
        for (int i = 1; i <= 10; i++) {
            final String temp = String.valueOf(i);

            new Thread(()->{
                myCache.get(temp);
            },String.valueOf(i)).start();
        }


    }
}

/**
 * 自定义缓存 get set 使用Map
 */
class MyCache{

    private volatile Map<String, Object> map = new HashMap<>();

    // 存 写
    public void put(String key, Object value) {
        System.out.println(Thread.currentThread().getName() + "写入");
        map.put(key, value);
        System.out.println(Thread.currentThread().getName() + "写入完毕!");

    }

    // 读 取
    public void get(String key) {

        System.out.println(Thread.currentThread().getName() + "读取");
        Object o = map.get(key);
        System.out.println(Thread.currentThread().getName() + "读取完毕!");

    }
}

class MyCacheLock{

    private volatile Map<String, Object> map = new HashMap<>();
    // 读写锁 更加细粒度的操作
    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

   // private ReentrantLock lock = new ReentrantLock(); // 一般的可重入锁

    // 存 写
    // 写入的时候,只希望同时只有一个线程写
    public void put(String key, Object value) {

        readWriteLock.writeLock().lock(); // 加一个读写锁的写锁

        try {
            System.out.println(Thread.currentThread().getName() + "写入");
            map.put(key, value);
            System.out.println(Thread.currentThread().getName() + "写入完毕!");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.writeLock().unlock(); // 解锁
        }

    }

    // 读 取   加读锁的的目的:防止产生脏数据(写入的时候有读操作)
    // 所有人都可以读
    public void get(String key) {

        readWriteLock.readLock().lock(); // 加 读锁

        try {

            System.out.println(Thread.currentThread().getName() + "读取");
            Object o = map.get(key);
            System.out.println(Thread.currentThread().getName() + "读取完毕!");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.readLock().unlock(); // 解锁
        }

    }
}
posted @ 2021-07-15 17:10  夕立君  阅读(54)  评论(0编辑  收藏  举报