并发编程juc包学习2-锁

文章参考:https://blog.csdn.net/androidsj/article/details/80239640
锁的实现原理:https://blog.csdn.net/weixin_41240817/article/details/92112665
synchronized详细解析: https://mp.weixin.qq.com/s/g79pBaGIyPh9u5cPfVQJqQ

并发编程juc包学习2-锁

ReentrantLock

ReentrantLock是一个可重入的互斥锁,又被称为”独占锁”。
➣ ReentrantLock锁在同一个时间点只能被一个线程锁持有;而可重入的意思是,
ReentrantLock锁,可以被单个线程多次获取。
➣ ReentrantLock分为”公平锁”和“非公平锁”。它们的区别体现在获取锁的机制
上是否公平以及执行速度上。
➣ ReentrantLock是通过一个FIFO的等待队列来管理获取该锁所有线程的。
ReentrantLock是一个独占锁,在获取锁的之后其所有的操作是线程独享的,其它的线程在没有获取到锁之前都需要进行等待。

condition

是按照条件进行加锁和解锁的类
➣ Condition的作用是对锁进行更精确的控制。Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signalAll()相当于Object的notifyAll()方法。不同的是,Object中的wait()、notify()、notifyAll()方法是和”同步锁”/“共享锁”捆绑使用的。

使用

包含了使用ReentrantLock 已经Condition条件
目的:多线程打印abc

/**
 * 测试ReentrantLock和Condition
 * 作用:按照条件解锁某一个线程,更加方便控制线程之间的协同
 */
public class TestCondition {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //true表示这是一个公平锁
        ReentrantLock lock = new ReentrantLock();
        Condition condition1 = lock.newCondition();
        Condition condition2 = lock.newCondition();

        executorService.execute(() -> {
            try {
                lock.lock();
                //监听c1,当有线程唤醒c1就开始往下走
                condition1.await();
                System.out.println("b");
                //唤醒c2,当有线程监听c2就会继续执行
                condition2.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });

        executorService.execute(() -> {
            try {
                lock.lock();
                condition2.await();
                System.out.println("c");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });

        //作为起始入口的第一个执行的线程要放在最后,保证其他已经await后,在进行signal
        executorService.execute(() -> {
            try {
                lock.lock();
                System.out.println("a");
                condition1.signal();//唤醒c1
            }finally {
                lock.unlock();
            }
        });
        executorService.shutdown();
    }
}

ReadWriteLock

所谓的读写锁指的是有两把锁,在进行数据写入的时候有一把”写锁”,而在进行数据读取的时候有一把”读锁”,很明显写锁一定会实现线程安全同步处理操作,而读锁可以被多个对象读取获得。
➣ 分为读锁和写锁,多个读锁不互斥(共享锁),读锁与写锁互斥,这是由jvm自己控制的,开发者只要上好相应的锁即可;
➣ ReentrantReadWriteLock会使用两把锁来解决问题,一个读锁(多个线程可以同时读),一个写锁(单个线程写)。
➣ ReadLock可以被多个线程持有并且在作用时排斥任何的WriteLock,而WriteLock则是完全的互斥,这一特性最为重要, 因为对 于高读取频率而相对较低写入的数据结构,使用此类锁同步机制则可以提高并发量;

使用实例

目的:模拟银行多线程存钱和多线程查询的数据一致

/**
 * 测试读写锁,模拟银行存取钱
 */
public class TestReadWriteLock {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //共享同一个账户
        Account account = new Account();
        
        //20个存钱线程
        for (int i = 0; i < 20; i++) {
            executorService.execute(() -> {
                account.saveMoney(20);
            });
        }

        //10个查询线程
        for (int i = 0; i < 10; i++) {
            Future<Integer> submit = executorService.submit(() -> {
                return account.readMoney();
            });
            try {
                System.out.println("查询账户" + submit.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        executorService.shutdown();
    }
}

class Account {
    private int money = 10;
    private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    
    public void saveMoney(int i) {
        //获取写锁
        ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
        //写锁
        writeLock.lock();
        try {
            System.out.println("存入前余额" + money);
            this.money = money + i;
            System.out.println(Thread.currentThread().getName() + "存入" + i);
            System.out.println("存入后余额" + money);
        } finally {
            writeLock.unlock();
        }
    }

    public int readMoney() {
        //同理使用读锁
        readWriteLock.readLock().lock();
        try {
            return money;
        } finally {
            readWriteLock.readLock().unlock();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值