博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java多线程初学者指南(11):使用Synchronized块同步方法
阅读量:5934 次
发布时间:2019-06-19

本文共 2926 字,大约阅读时间需要 9 分钟。

  synchronized
关键字有两种用法。第一种就是在
一文中所介绍的直接用在方法的定义中。另外一种就是
synchronized
块。我们不仅可以通过
synchronized
块来同步一个对象变量。也可以使用
synchronized
块来同步类中的静态方法和非静态方法。
synchronized
块的语法如下:
public
 
void
 method()
{
    … …
    
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
块的参数来达到同样的效果。
在内类(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())
       {
            
       }
    }
     
}
在上面代码中通过一个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块同步类方法时应注意。
 本文转自 androidguy 51CTO博客,原文链接:http://blog.51cto.com/androidguy/214824,如需转载请自行联系原作者
你可能感兴趣的文章
使用Xtrabackup进行MySQL备份
查看>>
LogStash 安装配置初体验
查看>>
The Java™ Tutorials:Swing
查看>>
JFinal QuartzPlugin
查看>>
python新手入门
查看>>
VMware ESXi的安装和配置
查看>>
Linux如何开启mysql远程连接
查看>>
Android项目目录结构介绍
查看>>
计算机互访
查看>>
mxgraph
查看>>
Linux中Kill进程的N种方法
查看>>
一步步实现Spring框架(二)XML注入
查看>>
Spring Cloud Alibaba迁移指南2:一行代码从Hystrix迁移到Sentinel
查看>>
IntelliJ IDEA 乱码解决方案 (项目代码、控制台等)
查看>>
scala中tuple(一)
查看>>
lvm逻辑卷管理
查看>>
Linux链接概念
查看>>
单播、多播(组播)和广播的区别
查看>>
学习Linux坚持贴!第二天
查看>>
MySQL如何实现分库分表,如何提高查询效率
查看>>