synchronized的解读

synchronized是用来控制线程同步的,在多线程的情况下保证代码不被同时执行。synchronized的使用情况有下面几种

1、修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁

2、修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁

3、修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁

 

在不用synchronized的情况下看如下代码:

private static int number = 0;
class Demo implements Runnable{
    @Override
    public void run() {
        for(int j=0;j<200000;j++){
            add();
        }
    }

    private void add(){
        number++;
    }
}
Demo demo = new Demo();
Thread thread = new Thread(demo);
Thread thread2 = new Thread(demo);
Thread thread3 = new Thread(demo);
thread.start();
thread2.start();
thread3.start();
    try {
        thread.join();
        thread2.join();
        thread3.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

System.out.println("线程结束number:"+number);

结果如下:

并不是预期的600000.由于++该操作是先读取值,然后写回一个新值,相当于原来的值加上1,分两步完成,如果第二个线程在第一个线程读取旧值和写回新值期间读取i的域值,那么第二个线程就会与第一个线程一起看到同一个值,并执行相同值的加1操作,这也就造成了线程安全失败。加上synchronized,代码修改如下:

class Demo implements Runnable{
    @Override
    public void run() {
        for(int j=0;j<200000;j++){
            add();
        }
    }

    private synchronized void add(){
        number++;
    }
}

再次运行结果如下:

上面的synchronized是在方法上面的,属于第一种当前实例加锁,如果不用同一个对象,new多个对象结果会怎样?看如下代码

Thread thread = new Thread(new Demo());
Thread thread2 = new Thread(new Demo());
Thread thread3 = new Thread(new Demo());
thread.start();
thread2.start();
thread3.start();
    try {
        thread.join();
        thread2.join();
        thread3.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

System.out.println("线程结束number:"+number);

结果如下:

同样结果不是600000.因为synchronized修饰方法,是对该对象的锁,新建不同对象的时候就会出现同时运行加的方法

 

下面我们来看看第二种,修饰静态方法:

代码修改如下:

    Thread thread = new Thread(new Demo());
    Thread thread2 = new Thread(new Demo());
    Thread thread3 = new Thread(new Demo());
    thread.start();
    thread2.start();
    thread3.start();
        try {
            thread.join();
            thread2.join();
            thread3.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    System.out.println("线程结束number:"+number);
}
private static int number = 0;
class Demo implements Runnable{
    @Override
    public void run() {
        for(int j=0;j<200000;j++){
            add();
        }
    }
    
}

private static synchronized void add(){
    number++;
}

结果如下:

synchronized 修饰静态方法,其实就是对类的加锁,所以结果也是600000,同理,在代码块中加上synchronized (xxx.class)也是对类的加锁,同时synchronized (Object o)就是对对象o的锁,这两种就是用于代码块的使用。另外synchronized (this)是对该类的实例对象的加锁。其实也不复杂,自己调试一下就清楚了,下面有张图片,便于记忆

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值