文档章节

Java并发编程初级篇(十四):使用读写所实现同步机制

阿拉德大陆的魔法师
 阿拉德大陆的魔法师
发布于 2016/11/25 11:29
字数 939
阅读 18
收藏 0

Java API除了提供Lock()接口之外,还为我们提供了一个读写锁接口ReadWriteLock,使用这个锁的实现类ReentrantReadWriteLock可以让我们把读锁和写锁进行分离,对同步数据进行修改的时候使用写锁,这时候其他需要获取写锁的线程会被挂起,同时使用读锁的线程也会被挂起。而读取数据的时候使用读锁,这时候使用读锁的线程可以并发访问,以提高效率。

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();
}

我们模拟一个修改价格的例子,来看一下读锁与写锁是如何使用的。

创建一个价格类,里面两个商品的价格以及一个读写锁。在修改价格的方法里我们使用写锁,在读取商品价格的方法里我们使用读锁。修改商品价方法休眠两秒来模拟修改价格的过程,并打印修改价格信息。

public class PriceInfo {
    private double price1;
    private double price2;
    private ReadWriteLock lock;

    public PriceInfo() {
        price1 = 1.0;
        price2 = 2.0;
        lock = new ReentrantReadWriteLock();
    }

    public double getPrice1() {
        lock.readLock().lock();
        double value = price1;
        lock.readLock().unlock();
        return price1;
    }

    public double getPrice2() {
        lock.readLock().lock();
        double value = price2;
        lock.readLock().unlock();
        return price2;
    }

    public void setPrice(double price1, double price2) {
        lock.writeLock().lock();
        System.out.printf("Writer: Attemp to modify the price! Price1:%f Price2:%f\n", price1, price2);
        this.price1 = price1;
        this.price2 = price2;
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.printf("Writer: Price has been modified: Price1:%f Price2:%f\n", price1, price2);
        lock.writeLock().unlock();
    }
}

创建一个价格修改线程,随机休眠一定时间后修改价格。

public class Writer implements Runnable{
    private PriceInfo priceInfo;

    public Writer(PriceInfo priceInfo) {
        this.priceInfo = priceInfo;
    }

    @Override
    public void run() {
        double price1 = Math.random() * 10;
        double price2 = Math.random() * 8;

        try {
            Thread.sleep((long) (Math.random() * 10000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        priceInfo.setPrice(price1, price2);
    }
}

创建一个价格读取线程,每次读取两个商品的价格并打印。

public class Reader implements Runnable {
    private PriceInfo priceInfo;

    public Reader(PriceInfo priceInfo) {
        this.priceInfo = priceInfo;
    }

    @Override
    public void run() {
        Date date = new Date();
        System.out.printf("%s: Price1 %f .%s\n",
                Thread.currentThread().getName(), priceInfo.getPrice1(), date);
        System.out.printf("%s: Price2 %f .%s\n",
                Thread.currentThread().getName(), priceInfo.getPrice2(), date);
    }
}

创建主方法类,启动三个价格修改线程。然后每个两秒启动一个线程读取商品价格。

public class Main {
    public static void main(String[] args) {
        PriceInfo priceInfo = new PriceInfo();

        for (int i = 0; i < 3; i++) {
            Thread threadWriter = new Thread(new Writer(priceInfo));
            threadWriter.start();
        }

        while (true) {
            new Thread(new Reader(priceInfo)).start();
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

查看控制台日志,每次读取价格都是修改价格之后的新价格,并且在修改价格的2秒内,读取价格线程处于挂起状态。

Thread-3: Price1 1.000000 .Fri Nov 25 11:16:35 CST 2016
Thread-3: Price2 2.000000 .Fri Nov 25 11:16:35 CST 2016
Writer: Attemp to modify the price! Price1:9.655775 Price2:4.031177
Writer: Price has been modified: Price1:9.655775 Price2:4.031177
Thread-4: Price1 9.655775 .Fri Nov 25 11:16:37 CST 2016
Thread-4: Price2 4.031177 .Fri Nov 25 11:16:37 CST 2016
Thread-5: Price1 9.655775 .Fri Nov 25 11:16:39 CST 2016
Thread-5: Price2 4.031177 .Fri Nov 25 11:16:39 CST 2016
Writer: Attemp to modify the price! Price1:2.347803 Price2:2.088409
Writer: Price has been modified: Price1:2.347803 Price2:2.088409
Thread-6: Price1 2.347803 .Fri Nov 25 11:16:41 CST 2016
Thread-6: Price2 2.088409 .Fri Nov 25 11:16:41 CST 2016
Thread-7: Price1 2.347803 .Fri Nov 25 11:16:43 CST 2016
Thread-7: Price2 2.088409 .Fri Nov 25 11:16:43 CST 2016
Writer: Attemp to modify the price! Price1:0.981288 Price2:6.281034
Writer: Price has been modified: Price1:0.981288 Price2:6.281034
Thread-8: Price1 0.981288 .Fri Nov 25 11:16:45 CST 2016
Thread-8: Price2 6.281034 .Fri Nov 25 11:16:45 CST 2016
Thread-9: Price1 0.981288 .Fri Nov 25 11:16:47 CST 2016
Thread-9: Price2 6.281034 .Fri Nov 25 11:16:47 CST 2016
Thread-10: Price1 0.981288 .Fri Nov 25 11:16:49 CST 2016
Thread-10: Price2 6.281034 .Fri Nov 25 11:16:49 CST 2016
Thread-11: Price1 0.981288 .Fri Nov 25 11:16:51 CST 2016
Thread-11: Price2 6.281034 .Fri Nov 25 11:16:51 CST 2016

 

© 著作权归作者所有

共有 人打赏支持
阿拉德大陆的魔法师
粉丝 25
博文 91
码字总数 83019
作品 0
西城
程序员
私信 提问
【死磕Java并发】—– 死磕 Java 并发精品合集

【死磕 Java 并发】系列是 LZ 在 2017 年写的第一个死磕系列,一直没有做一个合集,这篇博客则是将整个系列做一个概览。 先来一个总览图: 【高清图,请关注“Java技术驿站”公众号,回复:脑...

chenssy
07/22
0
0
再有人问你Java内存模型是什么,就把这篇文章发给他!

前几天,发了一篇文章,介绍了一下JVM内存结构、Java内存模型以及Java对象模型之间的区别。有很多小伙伴反馈希望可以深入的讲解下每个知识点。Java内存模型,是这三个知识点当中最晦涩难懂的...

技术小能手
09/30
0
0
【Java并发专题】27篇文章详细总结Java并发基础知识

努力的意义,就是,在以后的日子里,放眼望去全是自己喜欢的人和事! github:https://github.com/CL0610/Java-concurrency,欢迎题issue和Pull request。所有的文档都是自己亲自码的,如果觉...

你听___
05/06
0
0
17《Java核心技术》之synchronized底层如何实现?什么是锁的升级、降级?

一、提出问题 我们在上一篇中对比和分析了 synchronized 和 ReentrantLock,算是进入并发编程阶段的热身,相信你已经对线程安全,以及如何使用基本的同步机制有了基础,今天我们将深入了解 ...

飞鱼说编程
11/12
0
0
再有人问你Java内存模型是什么,就把这篇文章发给他。

前几天,发了一篇文章,介绍了一下JVM内存结构、Java内存模型以及Java对象模型之间的区别。有很多小伙伴反馈希望可以深入的讲解下每个知识点。Java内存模型,是这三个知识点当中最晦涩难懂的...

Java架构
07/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

CentOS配置Tomcat监听80端口,虚拟主机

Tomcat更改默认端口为80 更改的配置文件是: /usr/local/tomcat/conf/server.xml [root@test-a ~]# vim /usr/local/tomcat/conf/server.xml # 找到 Connector port="8080" protocol="HTTP/1......

野雪球
今天
5
0
《稻盛和夫经营学》读后感心得体会3180字范文

《稻盛和夫经营学》读后感心得体会3180字范文: 一代日本经营之圣稻盛和夫凭借刻苦勤奋的精神以及深植于佛教的商业道德准则,成为了“佛系”企业家的代表人物。在《稻盛和夫经营学》“领导人...

原创小博客
今天
3
0
java框架学习日志-5(常见的依赖注入)

依赖注入(dependency injection) 之前提到控制反转(Inversion of Control)也叫依赖注入,它们其实是一个东西,只是看的角度不同,这章详细说一下依赖注入。 依赖——指bean对象创建依赖于...

白话
今天
4
0
红外接收器驱动开发

背景:使用系统的红外遥控软件没有反应,然后以为自己接线错误,反复测试,结果烧坏了一个红外接收器,信号主板没有问题。所以自己开发了一个红外接收器的python驱动。接线参见https://my.os...

mbzhong
今天
2
0
ActiveMQ消息传送机制以及ACK机制详解

AcitveMQ是作为一种消息存储和分发组件,涉及到client与broker端数据交互的方方面面,它不仅要担保消息的存储安全性,还要提供额外的手段来确保消息的分发是可靠的。 一. ActiveMQ消息传送机...

watermelon11
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部