小伙伴们是否知道什么是synchronized吗?的确,翻译过来就是同步。那我们为什么使用同步呢?在Java中java是如何使用synchronized的呢?让我们一起了解下吧。
1.如何在Java中使用synchronized块。
简单地说,在多线程环境中,当两个或多个线程同时尝试更新可变共享数据时,就会发生竞争条件。Java提供了一种通过同步对共享数据的线程访问来避免竞争条件的机制。标记为synchronized的逻辑变为同步块,在任何给定时间只允许一个线程执行。
2.为什么同步?
让我们考虑一个典型的竞争条件,我们计算总和,多个线程执行calculate()方法:
让我们写一个简单的测试:
我们只是使用带有3线程池的ExecutorService来执行1000次计算()。
如果我们按顺序执行,预期的输出将是1000,但我们的多线程执行几乎每次都会失败,实际输出不一致,例如:
这个结果当然不是意料之外的。
避免竞争条件的一种简单方法是使用synchronized关键字使操作成为线程安全的。
3. 同步关键字
该同步关键字可以以不同级别被使用:
· 实例方法
· 静态方法
· 代码块
当我们使用synchronized块时,内部Java使用监视器(也称为监视器锁或内部锁)来提供同步。这些监视器绑定到一个对象,因此同一对象的所有同步块只能有一个线程同时执行它们。
3.1 Synchronized实例方法
只需在方法声明中添加synchronized关键字即可使方法同步:
请注意,一旦我们同步该方法,测试用例就会通过,实际输出为1000:
实例方法在拥有该方法的类的实例上同步。这意味着每个类的实例只能有一个线程可以执行此方法。
3.2 Synchronized static方法
静态方法与实例方法一样是同步的:
这些方法在与该类关联的Class对象上同步,并且由于每个JVM每个类只存在一个Class对象,因此每个类只能在一个静态同步方法内执行一个线程,而不管它具有多少个实例。
我们来试试吧:
3.3 方法中的同步块
有时我们不想同步整个方法,只需要同步其中的一些指令。这可以通过将 synchronized应用于块来实现:
让我们测试一下这个变化:
请注意,我们将参数this传递给synchronized块。这是监视器对象,块内的代码在监视器对象上获得同步。简而言之,每个监视器对象只能在该代码块内执行一个线程。
如果方法是静态的,我们将传递类名来代替对象引用。该类将成为块同步的监视器:
让我们在静态方法中测试块:
以上就是对java中synchronized的用法的总结,是否对synchronized有了更多的了解呢?想要了解跟多知识,请继续关注本站。