栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

第14章 多线程(4) Lock 条件对象与 synchronized 方法

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

第14章 多线程(4) Lock 条件对象与 synchronized 方法

 

 14.5.4 条件对象

锁应该加在哪里?

答:if/switch/三目/循环 条件判定中,使用了线程共享的变量前后,需要加锁。

非线程共用变量,不同线程,同时处理是安全的(比如局部变量)。他们的值不会因为线程切换受到影响。

线程共用变量,非条件判定语句处理如果是原子操作(原子加法),或者不改变值是安全的(比如打印)

条件判定结果受到共享变量的影响,可能在判定后切换线程,然后再次切回当前线程后不满足条件继续执行后续语句,导致条件失效。

因为线程共享的变量(条件对象)受到不同线程切换的影响,所以,锁可以针对不同对象进行“上锁”操作。

获取条件:Condition condition = lock.newCondition();

不满足条件时进行等待,直到唤醒:condition. await()

可能满足其他条件,随机结束阻塞:condition. signal(),全部解除阻塞:condition. signalAll()

❤李癩❤李癩❤李癩

public class Bank {
    private final double[] accounts;
    private Lock bankLock;
    private Condition sufficientFunds;
    public Bank(int n, double initialBalance){
        accounts = new double[n];
        for(int i = 0; i < n; i++){
            accounts[i] = initialBalance;
        }
 
        bankLock = new ReentrantLock();
        sufficientFunds = bankLock.newCondition();
    }
  
    public void transfer(int from, int to, double amount) throws InterruptedException {
        bankLock.lock();
        while(accounts[from] < amount)
            sufficientFunds.await();
 
        try{
            System.out.print(Thread.currentThread());
            accounts[from] -= amount;
            System.out.printf(" %10.2f from %d to %d", amount, from, to);
            accounts[to] += amount;
            System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
            sufficientFunds.signalAll();
        }finally {
            bankLock.unlock();
        }
 
    }
  
    private double getTotalBalance(){
        bankLock.lock();
        try{
            double sum = 0;
            for(double a: accounts){
                sum += a;
            }
 
            return sum;
        }finally {
            bankLock.unlock();
        }
 
    }
  
    public int size(){
        return accounts.length;
    }
}

❤李癩❤李癩❤李癩

结果:

尿寮

尿寮

以上代码,具有一定的死锁风险。比如线程1 需要线程2转1000块,线程2需要线程1转1000块,两者都等待对方转1000块,才有足够的钱进行转账,会造成死锁

死锁:2或多个已经锁定的线程都在阻塞,等待对方释放锁,造成循环等待。比如1号房间钥匙扔2号房间,2号房间钥匙扔三号房间,3号房间钥匙扔1号房间,然后把三个房间的都关好,则三个房间都无法打开,造成死锁。

 14.5.5 synchronized

锁和条件的用途:

唯一:任何时间只有一个线程进行执行

可控:锁可以管理进入保护段的线程

条件:可以加入一个或多个条件对象

阻塞:条件可阻塞代码段继续运行

可使用 synchronized 方法,保护整个方法,也就是说相当于前后加锁解锁:

❤李癩❤李癩❤李癩

public void transfer(int from, int to, double amount) throws InterruptedException {

        bankLock.lock();

        while(accounts[from] < amount)

            sufficientFunds.await();



        try{

            System.out.print(Thread.currentThread());

            accounts[from] -= amount;

            System.out.printf(" %10.2f from %d to %d", amount, from, to);

            accounts[to] += amount;

            System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());

            sufficientFunds.signalAll();

        }finally {

            bankLock.unlock();

        }



    }

❤李癩❤李癩❤李癩

等价于:

❤李癩❤李癩❤李癩

 public synchronized void transfer(int from, int to, double amount) throws InterruptedException {

        while(accounts[from] < amount)

            sufficientFunds.await();



        System.out.print(Thread.currentThread());

        accounts[from] -= amount;

        System.out.printf(" %10.2f from %d to %d", amount, from, to);

        accounts[to] += amount;

        System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());

        sufficientFunds.signalAll();

        

    }

❤李癩❤李癩❤李癩

那如果用了非 Lock, 如何进行阻塞呢?这就要用到 Obejct 类的相关方法:

 notifyAll() 等价于 signalAll()

 notify() 等价于 signal()

 wait() 等价于 await()

锁与条件的局限性:

 阻塞线程不能中断

 锁不能设定超时时间

 所得条件比较单一

作者的建议:

 Lock+Condition 和 synchronized 两种方法都不够优秀,后续会介绍更好的方法;

 尽量用 synchronized , 减少出错几率

 特别需要指定锁时(比如可重入锁特性),才使用 Lock+Condition

相关内容:选择 《Java核心技术 卷1》查找相关笔记

评论点赞收藏✨关注,是送给作者最好的礼物,愿我们共同学习,一起进步

如果对作者发布的内容感兴趣,可点击下方关注公众号 钰娘娘知识汇总 查看更多作者文章哦!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/830135.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号