06并发编程_显示锁

显示锁

Lock接口和核心方法

lock() 加锁操作

unlock()  解锁操作

tryLock()

加锁就需要解锁,写代码一定要在finally中记得解锁

public class LockDemo {

    private Lock lock = new ReentrantLock();
    private int count ;

    public void increntCountByLock(){
        lock.lock();
        try{
            count++;
        }finally{
         lock.unlock();
        }
    }

可重入锁 ReentrantLock所谓锁的公平和非公平

       如果在时间上,先对锁进行获取的请求,一定先被满足,这个锁是公平的,不满足,就是非公平的

非公平锁的效率一般比较高

公平锁和非公平锁效率的比较原理

例如3个线程A,B,C操作一个共享资源,线程 A先获得了共享资源的锁进行操作,此时线程B要对共享资源操作,由于没有获得锁,所以被挂起(挂起和阻塞不是一个概念:挂起是CPU暂时不管,而阻塞是没有满足执行的条件),此时线程C也要来操作共享资源,由于线程B是被挂起的,如果需要将线程B从挂起状态变为运行状态,需要消耗一定的时间,所以先执行活跃的线程C,这样就节约了这个时间,就是非公平锁,如果是公平锁,就会先让B操作,这样效率没有非公平锁效率高了

      ReentrantLock构造方法 默认的是公平所,如果需要非公平所

     ReentrantLock lock = new ReentrantLock(false)非公平锁

ReadWriteLock接口和读写锁 ReentrantReadWriteLock,什么情况下用读写锁?

ReentrantLock和Synchronized 都是排它锁,一个时刻只允许一个线程操纵

         读写锁:同一时刻允许多个读线程同时访问,但是写线程访问的时候,所有的读和写都被阻塞,最适合读多写少的场景

Lock接口和Synchronized的比较

Synchronized 代码简洁,获取锁可以中断,

Lock 获取锁可以被中断,超时获取锁,尝试获取锁,读多写少用读写锁

代码实现 需要操作的共享变量GoodsInfo

public class GoodsInfo {

    private  final String name;
    private double totalMoney;
    private int storeNumber;

    public GoodsInfo(String name, double totalMoney, int storeNumber) {
        this.name = name;
        this.totalMoney = totalMoney;
        this.storeNumber = storeNumber;
    }

    public double getTotalMoney(){
        return totalMoney;
    }

    public  int getStoreNumber(){
        return storeNumber;
    }

    public void changeNumber(int sellNumber){
        this.totalMoney +=sellNumber*25;
        this.storeNumber -= sellNumber;
    }
}

接口类GoodService

public interface GoodService {

    public GoodsInfo getNum();//获得商品信息
    public void setNum(int num); //设置商品数量

}

接口实现类UserRWLock 和Synchronized 比较 两个实现类分别实现接口方法

public class UserRWLock implements GoodService{

    private GoodsInfo goodsInfo;
    private final ReadWriteLock lock = new ReentrantReadWriteLock(false);
    private final Lock getLock = lock.readLock();//读锁
    private final Lock setLock = lock.writeLock();//写锁

    public UserRWLock(GoodsInfo goodsInfo) {
        this.goodsInfo = goodsInfo;
    }

    @Override
    public GoodsInfo getNum() {
        getLock.lock();
        try{
            SleepTools.ms(5);
            return this.goodsInfo;
        }finally {
            getLock.unlock();
        }

    }

    @Override
    public void setNum(int num) {
        setLock.lock();
        try{
            SleepTools.ms(5);
            goodsInfo.changeNumber(num);
        }finally{
            setLock.unlock();
        }
    }
}
public class UseSync implements GoodService {

    private GoodsInfo goodsInfo;

    public UseSync(GoodsInfo goodsInfo){
        this.goodsInfo = goodsInfo;
    }
    @Override
    public synchronized GoodsInfo getNum() {
        try {
            Thread.sleep(5);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this.goodsInfo;
    }

    @Override
    public  synchronized void setNum(int num) {
        try {
            Thread.sleep(5);
        } catch (Exception e) {
            e.printStackTrace();
        }
        goodsInfo.changeNumber(num);
    }
}

工具类

public class SleepTools {

    public static void ms(int second){
        try {
            Thread.sleep(second);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

测试类比较两种锁的性能差异 main方法中有注释的是第二种锁的调用,日志信息就打印了,实例代码都在文中有展示,自行运行比较时间可以得出上面比较结论

public class BusiApp {

    static final int readWriteRatio = 10; //读写线程的比例
    static final int minthreadCount = 3; //最少线程

    private static class GetThread implements Runnable{

        private GoodService goodService;

        public GetThread(GoodService goodService){
            this.goodService = goodService;
        }

        @Override
        public void run() {
            long start = System.currentTimeMillis();
            for (int i = 0; i < 100; i++) {
                goodService.getNum();
            }
            System.out.println(Thread.currentThread().getName()
                    + "读取商品耗时:"+ (System.currentTimeMillis()-start) + "ms");
        }
    }
    //写操作
    private static class SetThread implements Runnable{

        private GoodService goodService;

        public SetThread(GoodService goodService){
            this.goodService = goodService;
        }
        @Override
        public void run() {
            long start = System.currentTimeMillis();
            Random r = new Random();
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                goodService.setNum(r.nextInt(10));
            }
            System.out.println(Thread.currentThread().getName()
                    + "写商品耗时:"+(System.currentTimeMillis()-start) + "ms----");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        GoodsInfo goodsInfo = new GoodsInfo("CPU",100000,10000);
        //GoodService goodsService = new UseSync(goodsInfo);
        GoodService goodsService = new UserRWLock(goodsInfo);
        for (int i = 0; i < minthreadCount; i++) {
            Thread setT = new Thread(new SetThread(goodsService));
            for (int j = 0; j < readWriteRatio ; j++) {
                Thread getT = new Thread(new GetThread(goodsService));
                getT.start();
            }
            Thread.sleep(100);
            setT.start();
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值