【Java】多线程基础(四)

4. 线程同步

书接上回,在使用多线程场景中,可能会存在不同的线程操作同一个数据,例如我们小学题目中常见的 一边放水一边蓄水一边存钱一边花钱,我们就以存钱为例,一个线程存钱,一个线程取钱,如果两个线程同时操作,取钱的时候也在存钱,比如此刻余额为 100,取50,存 50,那么存钱的线程存完钱的时候是 150,而取钱之后是 50,这两边的结果其实都是不对的,需要进行同步。才能让存取之后的余额一致。下面就介绍几种线程同步的方法。 同步的核心就是 加锁 -> 修改->释放锁

4.1 同步代码块

同步代码块其实就是将并行执行的代码,使用 synchronized 关键字进行同步,其使用方式为:

Object obj = new Object();  //监视器

public void foo(){
    ...
    synchronized(obj) { //同步代码块
        doSomething();
    }
    ...
}

当线程运行 foo 方法时,运行到同步代码块部分,需要先获取监视器的锁定,如果监视器已经被其他线程获取,那么此时就进入了阻塞状态,等到监视器被释放后,则可以被其他线程继续竞争获取,从而保证了同步代码块中每时每刻只有一个线程调用。

在 Java 中,任何对象都可以被当做监视器,也就是说synchronized(obj)中的 obj 可以换成其他对象,但是一般我们推荐将可能被多线程并发访问的对象作为监视器。例如上面存钱和取钱的例子中,我们可以用存取的账户对象作为监视器。放水和蓄水可以用水池作为监视器对象,等等。

4.2 同步方法

和同步代码块差不多 也是用到了 synchronized 关键字。与同步代码块不同的是,同步方法是加在方法的修饰上

public synchronized void foo(){
    doSomething();
}

通过同步代码块我们知道 synchronized 是获取了一个对象做监视器,在同步方法(非 static )中,这个监视器其实调用此方法的对象,也就是 this。

对于静态同步方法,其锁的就是这个类,对任意该类内静态同步方法,任意时刻只能有一个方法可以竞争到锁。由于同步方法和静态同步方法,锁的不是同一个对象,所以他们之间没有竞争关系。

静态同步方法如下

public synchronized static void bar(){
}

4.3 锁(Lock)

Java 中有很多锁,这里我们主要了解一下如何使用锁去控制同步访问资源。Lock与 synchronized相比,Lock 更加灵活,同时 Lock 还提供了 Condition 对象,可以应对不同情况的同步操作。

4.3.1 同步锁

锁的一般写法如下

class A {
    private final Lock lock = new ReentrantLock(); //创建锁对象
    
    public void foo(){
        lock.lock(); // 加锁
        try{
            doSomething();
        } catch(Exeception e){
            handleException();
        }finally{
            lock.unlock(); //解锁
        }
    }
}

同样的从代码可以看出 流程也是加锁 -> 修改->释放锁,这里我们看到最终解锁是在 finally 中调用的,是因为加锁和释放锁在不同的作用范围的时候,一定要确保解锁,所以在 finally 中调用解锁方法。

4.3.2 死锁

死锁的定义起始很简单,就是两个线程都在等待对方释放监视器,导致了死锁。我们举一个不太恰当的例子,两个人在打架斗殴,互相揪住了对方,都在说“你松手我就松手”,都在等着对方松手,导致一只纠缠。死锁的意思大概也就是如此。

那么我们如何避免死锁呢, 第一点我们要注意 在同步方法总避免调用相互调用。还有在使用同步锁的时候,如果使用了不同的 lock 对象,也要注意是否存在相互调用问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

0neXiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值