Java多线程初学者指南(11):利用Synchronized块同步要领
副标题#e#
synchronized要害字有两种用法。第一种就是在《利用Synchronized要害字同步类要领》一文中所先容的直接用在要领的界说中。别的一种就是synchronized块。我们不只可以通过synchronized块来同步一个工具变量。也可以利用synchronized块来同步类中的静态要领和非静态要领。
synchronized块的语法如下:
public void method()
{
… …
synchronized(表达式)
{
… …
}
}
一、非静态类要领的同步
从《利用Synchronized要害字同步类要领》一文中我们知道利用synchronized要害字来界说要领就会锁定类中所有利用synchronzied要害字界说的静态要领或非静态要领,但这并欠好领略。而假如利用synchronized块来到达同样的结果,就不难领略为什么会发生这种结果了。假如想利用synchronized块来锁定类中所有的同步非静态要领,需要利用this做为synchronized块的参数传入synchronized块国,代码如下:
通过synchronized块同步非静态要领
001 public class SyncBlock
002 {
003 public void method1()
004 {
005 synchronized(this) // 相当于对method1要领利用synchronized要害字
006 {
007 … …
008 }
009 }
010 public void method2()
011 {
012 synchronized(this) // 相当于对method2要领利用synchronized要害字
013 {
014 … …
015 }
016 }
017 public synchronized void method3()
018 {
019 … …
020 }
021 }
在上面的代码中的method1和method2要领中利用了synchronized块。而第017行的method3要领仍然利用synchronized要害字来界说要领。在利用同一个SyncBlock类实例时,这三个要领只要有一个正在执行,其他两个要领就会因未得到同步锁而被阻塞。在利用synchronized块时要想到达和synchronized要害字同样的结果,必需将所有的代码都写在synchronized块中,不然,将无法使当前要领中的所有代码和其他的要领同步。
除了利用this做为synchronized块的参数外,还可以利用SyncBlock.this作为synchronized块的参数来到达同样的结果。
#p#副标题#e#
在内类(InnerClass)的要领中利用synchronized块来时,this只暗示内类,和外类(OuterClass)没有干系。但内类的非静态要领可以和外类的非静态要领同步。如在内类InnerClass中加一个method4要领,并使method4要领和SyncBlock的三个要领同步,代码如下:
使内类的非静态要领和外类的非静态要领同步
public class SyncBlock
{
… …
class InnerClass
{
public void method4()
{
synchronized(SyncBlock.this)
{
… …
}
}
}
… …
}
在上面SyncBlock类的新版本中,InnerClass类的method4要领和SyncBlock类的其他三个要领同步,因此,method1、method2、method3和method4四个要领在同一时间只能有一个要领执行。
Synchronized块不管是正常执行完,照旧因为措施堕落而异常退出synchronized块,当前的synchronized块所持有的同步锁城市自动释放。因此,在利用synchronized块时不必担忧同步锁的释放问题。
二、静态类要领的同步
由于在挪用静态要领时,工具实例不必然被建设。因此,就不能利用this来同步静态要领,而必需利用Class工具来同步静态要领。代码如下:
通过synchronized块同步静态要领
public class StaticSyncBlock
{
public static void method1()
{
synchronized(StaticSyncBlock.class)
{
… …
}
}
public static synchronized void method2()
{
… …
}
}
在同步静态要领时可以利用类的静态字段class来获得Class工具。在上例中method1和method2要领同时只能有一个要领执行。除了利用class字段获得Class工具外,还可以利用实例的getClass要领来获得Class工具。上例中的代码可以修改如下:
利用getClass要领获得Class工具
public class StaticSyncBlock
{
public static StaticSyncBlock instance;
public StaticSyncBlock()
{
instance = this;
}
public static void method1()
{
synchronized(instance.getClass())
{
}
}
}
#p#分页标题#e#
在上面代码中通过一个public的静态instance获得一个StaticSyncBlock类的实例,并通过这个实例的getClass要领获得了Class工具(一个类的所有实例通过getClass要领获得的都是同一个Class工具,因此,挪用任何一个实例的getClass要领都可以)。我们还可以通过Class工具使差异类的静态要领同步,如Test类的静态要领method和StaticSyncBlock类的两个静态要领同步,代码如下:
Test类的method要领和StaticSyncBlock类的method1、method2要领同步
public class Test
{
public static void method()
{
synchronized(StaticSyncBlock.class)
{
}
}
}
留意:在利用synchronized块同步类要领时,非静态要领可以利用this来同步,而静态要领必需利用Class工具来同步。它们互不影响。虽然,也可以在非静态要领中利用Class工具来同步静态要领。但在静态要领中不能利用this来同步非静态要领。这一点在利用synchronized块同步类要领时应留意。