线程同步_线程同步的3种方法_线程同步和异步的区别

前言

本系列文章主要捋清楚Java多线程中的同步的各种使用方法,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题。

本篇文章主要聊一聊synchronized关键字。

阅读本文应该着重掌握如下技术点:

文章内容,来自博客园:像风一样。感兴趣的小伙伴可以移步自行关注。

一、synchronized同步方法

“非线程安全”其实会在多个线程对同一个对象中的实例变量进行并发访问时发生,产生的后果就是”脏读“,也就是读取到的数据其实是被更改过的。而“线程安全”就是已获得的实例变量的值是经过线程同步处理的,不会出现脏读的现象。

1.1、方法内的变量为线程安全

“非线程安全”问题存在于“实例变量”中,如果是方法内部的私有变量,则不存在“非线程安全”问题,所得结果也就是“线程安全”的了。

1.2、实例变量的非线程安全

如果多个线程共同访问1个对象中的实例变量,则有可能出现“非线程安全”问题。

用线程访问的对象中如果有多个实例对象,则运行的结果有可能出现交叉的情况。

如果对象仅有一个实例变量,则有可能出现覆盖的情况。

如果两个线程同时访问一个没有同步的方法,如果两个线程同时操作业务对象中的实例变量,则有可能出现“非线程安全”问题。解决这个问题的方法就是在方法前加关键字synchronized即可。

1.3、多个对象多个锁

代码示例:

线程同步_线程同步和异步的区别_线程同步的3种方法

上面示例是两个线程分别访问同一个类的两个不同实例的相同的同步方法,效果却是以异步的方式运行的。

本示例由于创建了2个业务对象,在系统中产生出2个锁,所以运行结果是异步的,打印的效果就是1 1。

当我们把线程2的参数service2改成service1,打印结果变为1 2。为什么是这样的结果?

关键字 synchronized 取得的线程对象都是对象锁,而不是把一段代码或方法(函数)当做锁,所以在上面的示例中,哪个线程先执行带synchronized关键字的方法,哪个线程就持有该方法所属对象的Lock,那么其他线程只能呈等待状态,前提是多个线程访问的是同一个对象。

但如果多个线程访问多个对象,则JVM会创建多个锁。

1.4、synchronized方法与锁对象

为了证明前面讲的线程锁是对象,示例代码如下:

线程同步的3种方法_线程同步_线程同步和异步的区别

运行结果:

begin: B

begin: A

end

end

在run方法前加入关键字synchronized进行同步处理。再次运行结果如下:

begin: A

end

begin: B

end

通过上面的实验得出结论,调用关键字synchronized声明的方法一定是排队运行的。另外需要牢牢记住“共享”这两个字,只有共享资源读写访问才需要同步化,如果不是共享资源,那么基本就没有同步的必要。

1.5、脏读

线程同步和异步的区别_线程同步的3种方法_线程同步

打印结果:

Thread-B : BB aa

出现脏读是因为getValue方法不是同步的,所以可以在任意时候进行调用。解决方法就是加上同步synchronized关键字,代码如下:

运行结果:

Thread-B : BB bb

通过上述示例不仅要知道脏读是通过synchronized关键字解决的,还要知道如下内容:

当A线程调用实例对象的加入synchronized关键字的X方法时,A线程就获得了X方法锁,更准确地讲,是获得了对象的锁,所以其他线程必须等A线程执行完毕了才可以调用X方法,但B线程可以随意调用其他的非synchronized同步方法。

脏读一定会出现操作实例变量的情况下,这就是不同线程“争抢”实例变量的结果。

1.6、synchronized锁重入

关键字synchronized拥有锁重入的功能,也就是在使用synchronized时,当一个线程得到一个对象后,再次请求此对象锁时是可以再次得到该对象的锁的。这也证明了在一个synchronized方法/块的内部调用本类的其他synchronized方法/块,是永远可以得到锁的。

示例代码:

线程同步和异步的区别_线程同步的3种方法_线程同步

“可重入锁”的概念是:自己可以再次获取自己的内部锁。可重入锁也支持在父子类继承的环境中。

示例代码:

线程同步的3种方法_线程同步和异步的区别_线程同步

说明子类是完全可以通过“可重入锁”调用父类的同步方法的。

1.7、出现异常,锁自动释放

当一个线程执行的代码出现异常时,其所持有的锁会自动释放。

1.8、同步不具有继承性

同步不可以继承。子类继承父类的同步方法时还需要添加synchronized关键字才能保持同步。

尾声

关于synchronized的使用细节是在是太多了,因为篇幅原因,暂时先写这么多。下篇文章《Java线程同步并不难:synchronized深入》继续~

限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: lzxmw777

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注