java锁:第四章:读写锁

2022-09-28 17:03:19 浏览数 (1)

理论:

未使用读写锁的代码:

代码语言:javascript复制
package com.javaliao.backstage;

import java.util.HashMap;
import java.util.Map;

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

    //写
    public void put(String key,Object value){
        System.out.println(Thread.currentThread().getName() "t 正在写入:" key);
        try {
            Thread.sleep(300);
            map.put(key,value);
            System.out.println(Thread.currentThread().getName() "t 写入完成");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //读
    public void get(String key){
        System.out.println(Thread.currentThread().getName() "t 正在读取");
        try {
            Thread.sleep(300);
            Object value = map.get(key);
            System.out.println(Thread.currentThread().getName() "t 读取完成:" value);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class Demo {

    public static void main(String[] args) {
        Data data = new Data();
        //五个写的线程
        for (int i = 0; i < 5; i  ) {
            final int tempInt = i;
            new Thread(()->{
                data.put(tempInt "",tempInt "");
            },String.valueOf(i)).start();
        }
        //五个读的线程
        for (int i = 0; i < 5; i  ) {
            final int tempInt = i;
            new Thread(()->{
                data.get(tempInt "");
            },String.valueOf(i)).start();
        }
    }
}

控制台:

可以看到写的操作原子性和独占性没有得到保证,0线程正在写入共享资源的时候,其他线程有写入和读取的共享资源操作,导致数据不一致。

是否可以添加Lock锁解决原子性和独占性的问题?

不可以,因为添加

代码语言:javascript复制
private Lock lock = new ReentrantLock();

只能保证一个线程读,不能让多个线程同时读取,不符合实际需求。

使用ReentrantReadWriteLock解决原子性和独占性,可以很好的解决并发性和数据的一致性

读写锁的代码:

代码语言:javascript复制
package com.javaliao.backstage;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;

class Data{
    private volatile Map map = new HashMap<String,Object>();
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void put(String key,Object value){
        //写锁
        lock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() "t 正在写入:" key);
            Thread.sleep(300);
            map.put(key,value);
            System.out.println(Thread.currentThread().getName() "t 写入完成");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.writeLock().unlock();
        }
    }

    public void get(String key){
        //读锁
        lock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() "t 正在读取");
            Thread.sleep(300);
            Object value = map.get(key);
            System.out.println(Thread.currentThread().getName() "t 读取完成:" value);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.readLock().unlock();
        }
    }
}


public class Demo {

    public static void main(String[] args) {
        Data data = new Data();
        //五个写的线程
        for (int i = 0; i < 5; i  ) {
            final int tempInt = i;
            new Thread(()->{
                data.put(tempInt "",tempInt "");
            },String.valueOf(i)).start();
        }
        for (int i = 0; i < 5; i  ) {
            final int tempInt = i;
            new Thread(()->{
                data.get(tempInt "");
            },String.valueOf(i)).start();
        }
    }
}

控制台:

比较:

0 人点赞