您当前的位置: 首页 >  Java

小志的博客

暂无认证

  • 2浏览

    0关注

    1217博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Java并发多线程编程——读写锁的理解与代码示例

小志的博客 发布时间:2021-04-26 22:37:25 ,浏览量:2

目录
    • 一、读写锁的理解
    • 二、读写锁的代码示例
    • 三、多个线程进行读操作的测试案例
    • 四、多个线程进行写操作的测试案例
    • 五、多个线程进行读写操作的测试案例

一、读写锁的理解
  • 读写锁实际维护了一对锁,一个读锁,一个写锁,通过分离读锁和写锁,使得其并发性比独占式锁(排他锁)有了很大的提升。
  • 读锁(共享锁):同一时刻可以允许多个线程访问共享资源。
  • 写锁(排他锁):在写线程访问的时候,所有的读线程和其他写线程都会被阻塞。即如果一个线程想要去写共享资源,就不应该再有其他线程可以对该共享资源进行读或者是写操作了。
二、读写锁的代码示例
package com.xz.thread.t11;

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.ReentrantReadWriteLock;

/**
 * @description: 读写锁代码示例
 * @author: xz
 */
public class Demo {
    //声明一个map,存储数据
    private Map map =new HashMap();
    /**
     *    1、ReentrantReadWriteLock实例实现了ReadWriteLock接口
     *    2、声明一个ReentrantReadWriteLock实例,指向父类ReadWriteLock的引用
     *       因为ReentrantReadWriteLock可以保证公平或者非公平
     *    3、ReadWriteLock类中只有readLock()和writeLock() 两个方法
     */
    private ReadWriteLock rwl =new ReentrantReadWriteLock();
    //读锁
    private Lock r =rwl.readLock();
    //写锁
    private Lock w =rwl.writeLock();

    //读操作,即获取数据方法
    public Object get(String key){
        r.lock();//获取读锁
        System.out.println(Thread.currentThread().getName()+"【读】操作正在执行--------");
        try {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return map.get(key);
        }finally {
            r.unlock();//释放读锁
            System.out.println(Thread.currentThread().getName()+"【读】操作执行完毕!!!!!");
        }
    }

    //写操作,即添加或修改数据方法
    public void put(String key,String value){
        w.lock();//获取写锁
        System.out.println(Thread.currentThread().getName()+"【写】操作正在执行========");
        try {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            map.put(key,value);
        }finally {
            w.unlock();//释放写锁
            System.out.println(Thread.currentThread().getName()+"【写】操作执行完毕!!!!!");
        }

    }
}

三、多个线程进行读操作的测试案例

1、代码

package com.xz.thread.t11;

/**
 * @description: 多个线程进行读操作的测试类
 * @author: xz
 */
public class ReadTest {
    public static void main(String[] args) {
        Demo d =new Demo();
        d.put("name","张三");

        //第一个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(d.get("name"));
            }
        }).start();

        //第二个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(d.get("name"));
            }
        }).start();

        //第三个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(d.get("name"));
            }
        }).start();
    }
}

2、输出结果 在这里插入图片描述 3、结论

  • 多个线程同时读一个资源类是没有任何问题的,所以为了满足在并发的情况下,读取共享资源是可以同时进行的。
四、多个线程进行写操作的测试案例

1、代码

package com.xz.thread.t11;

/**
 * @description: 多个线程进行写操作的测试类
 * @author: xz
 */
public class WriteTest {
    public static void main(String[] args) {
        Demo d =new Demo();

        //第一个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                d.put("name","张三");
            }
        }).start();

        //第二个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                d.put("name","李四");
            }
        }).start();

        //第三个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                d.put("name","王五");
            }
        }).start();
    }
}

2、输出结果 在这里插入图片描述 3、结论

  • 如果一个线程想要去写共享资源,就不应该再有其他线程可以对该共享资源进行读或者是写操作了。
五、多个线程进行读写操作的测试案例

1、代码

package com.xz.thread.t11;

/**
 * @description: 多个线程进行写操作和读操作的测试类
 * @author: xz
 */
public class WriteReadTest {
    public static void main(String[] args) {
        Demo d =new Demo();

        //第一个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                d.put("name","张三");
            }
        }).start();

        //第二个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                d.get("张三");
            }
        }).start();


    }
}

2、输出结果 在这里插入图片描述 3、结论

  • 在写线程访问的时候,所有的读线程和其他写线程都会被阻塞。
关注
打赏
1661269038
查看更多评论
立即登录/注册

微信扫码登录

0.0464s