java&Synchronized总结(上)

synchronized关键字

1.为什么要用synchronized?
在我们平时开发过程中,经常会听到线程安全,线程不安全的字眼。
线程不安全都是在多线程的环境下发生的,比如多个线程同时访问一个共享变量,这就会产生脏读的现象。
线程安全就是获得实例变量的值是经过同步处理的,不会出现脏读的现象。

2.synchronized同步方法:

2.1方法内部的变量线程安全

在这里插入图片描述
在这里插入图片描述

输出结果:
在这里插入图片描述
2.2变量线程不安全
在这里插入图片描述
输出结果:
在这里插入图片描述
上面是由于,两个线程访问一个共同访问一个对象的实例变量,从而导致了线程不安全的情况。

解决方法就是:在方法上加上synchronized关键字。
在这里插入图片描述
输出结果:
加上synchronized,同步访问,所以一定是输出完a在输出b,或者是输出完b在输出a。
在这里插入图片描述
2.3.多个对象多个锁
在这里插入图片描述

在这里插入图片描述
上面demo,演示两个线程访问同一个类的两个不同实例的相同名称的同步方法,从打印结果发现是异步执行?
解析:关键字synchronized取的锁都是对象锁,哪个线程先执行带synchronized关键字方法,哪个线程就持有该方法所属对象锁lock,那么其他线程只能呈等待状态。前提是多个线程访问的是同一个对象。,上面创建两个类的实例对象,所以jvm会创建多个锁。

2.4.synchronized方法与锁对象

在这里插入图片描述
在这里插入图片描述
输出结果:
在这里插入图片描述
将程序稍作修改:
在这里插入图片描述
在这里插入图片描述

通过上面的示例可以得出结论:调用synchronized的方法,一定是排队进行的,另外要牢牢记住共享两个字,只有共享资源的读写才需要同步化,如果不是共享资源,根本没有同步的必要。

假设我在一个共享资源类加一个普通方法,程序又会怎么运行呢?
在这里插入图片描述
在这里插入图片描述
我们可以看出虽然线程a持有对象锁,但是并不影响b线程调用非synchronized方法。

总结下结论:
1.A线程持有myObject对象锁,但是并不影响其他线程访问myObject对象中的非synchronized的方法。
2.A线程先获取对象锁,如果其他线程此时想要调用synchronized的方法,只能等待A线程释放锁,也就是满足同步的原则。

2.5.脏读
上面已经使用了多个线程调用同一个方法时,为了避免数据交叉的情况,使用synchronized关键字来进行同步。
虽然在赋值时进行了同步了,但是在取值的时候还是会出现一些意外,比如脏读,发生脏读是指在读取实例变量的时候,此值已经被其他线程更改过了。
在这里插入图片描述

在这里插入图片描述
输出结果:
在这里插入图片描述
那么怎么解决脏读的现象呢?
其实只要保证set线程和get线程是同一个锁对象即可,加上synchronized关键字。这样就能保证,get线程只能等待set线程释放完锁,才能
去访问同步方法。如下所示:
在这里插入图片描述
2.6.synchronized锁重入
关键字synchronized拥有锁重入的功能,也就是在使用synchronized时,当一个线程得到一个对象的锁的时候,再次请求此对象锁时可以再次得到该对象锁。这也证明在一个synchronized内部调用本类的其他synchronized方法时,是永远可时可以得到锁的。

在这里插入图片描述
在这里插入图片描述
输出结果:
在这里插入图片描述
看输出结果,上面示例主要是想说明2点:

1.线程A占有了对象锁,此时执行service1()方法,但是又要调用service2(),然后在调用servcie3(),因为service2(),service3()方法都是同步方法,这时候就可以重复使用这个锁对象,这就叫可重入,可以重复使用。

2在主线程休息0.2s后线程B尝试去调用service3(),但是线程A此时还在休眠中,所以并不会释放锁。所以线程b一定要等线程a可重入锁使用完毕,才能访问同步方法servcie3();所以打印顺序时如上面所示。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
上面的示例,存在子父类继承关系的时候,子类完全可以通过可重入锁调用父类中的同步方法。

2.7 出现异常,锁自动释放
在这里插入图片描述

在这里插入图片描述
输出结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值