Java 线程安全(二)-- synchronized

本文探讨了如何在Java中通过创建不同monitor对象,使得`setName`方法在`count`和`minus`同步执行时仍能独立访问。作者解释了`synchronized`的原理,并提供了使用`Object`标记实例,实现数据隔离的代码示例。
摘要由CSDN通过智能技术生成

第三种情况

public class Synchronized3Test {

    private int x = 0;

    private int y = 0;

    private String name;

    public void runTest() {

    }

    private synchronized void count(int newValue) {
        x = newValue;
        y = newValue;
    }

    private synchronized void minus(int del) {
        x -= del;
        y -= del;
    }

    private synchronized void setName(String newName) {
        name = newName;
    }

}

如代码所示,三个方法有可能同时被不同线程调用,尤其是加法和减法,同时被调用会导致数据同步异常

我们使用 synchronized 后,synchronized 保护的不是当前方法,而是方法中的数据

所以说,一旦用 synchronized 修饰之后,这个类当中的所有 synchronized 方法都不能被同时调用,也就是说一个 synchronized 方法被调用了,剩下的所有的 synchronized 不管跟当前方法中的变量有没有关系,都不能被调用了,为的就是防止出现以上加法和减法同时操作相同的变量时导致的数据不同步的问题

那么问题来了,我 setName 方法可以很清楚的看到跟另外两个方法没有关系,我想在另外两个方法当中的一个被调用的时候,这个方法也能被同时调用,应该怎么做呢?

在说解决方案之前,我们先来说一下,为什么会出现这种被 synchronized 修饰后,一个线程只能同时访问一个 synchronized 方法的原因,首先是,刚刚已经说过这样做的好处了,那是如何实现的呢?

在一个类中,有方法被 synchronized 修饰后,当前这个类就会有一个 monitor,来同时监管所有的 synchronized 修饰的方法,如果有线程正在执行其中一个方法,再有线程想要调用其中任意一个 synchronized 方法的话,都会被 monitor 拒绝,也就是说,所有的 synchronized 修饰的方法共用同一个 monitor。方便理解我们看图
在这里插入图片描述
既如此,那我们能不能创建多个 monitor,让彼此保护的数据互相有影响的方法使用一个 monitor,没有关系的使用新的 monitor 呢?

答案是可以的

我们修改代码

public class Synchronized3Test {

    .....

    private final Object monitor1 = new Object();
    private final Object monitor2 = new Object();

    private void count(int newValue) {
        synchronized (monitor1) {
            x = newValue;
            y = newValue;
        }
    }

    private void minus(int del) {
        synchronized (monitor1) {
            x -= del;
            y -= del;
        }
    }

    private void setName(String newName) {
        synchronized (monitor2) {
            name = newName;
        }
    }

}

如代码所示,我们创建两个标记,monitor1monitor2,让相关的保护内容使用同一个标记,也就是使用同一个 monitor,从而达到我们想要的效果

在这里插入图片描述
这里解释下使用 Object,创建标记的原因,因为只起到标记的作用,所以说用任何对象来标记都行,使用 String 也是可以的,我们当然使用最小的对象,没必要用 String 这个更大的对象

这里解释一下上面 synchronized 不同写法的作用

private synchronized void count() {
}

等同于

private void count() {
	synchronized (this) {
	}
}

他们都是使用的 this 这个 monitor,第一种写法一种简写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值