使用Synchronized块同步方法
synchronized关键字有两种用法。第一种就是在《使用Synchronized关键字同步类方法》一文中所介绍的直接用在方法的定义中。另外一种就是synchronized块。我们不仅可以通过synchronized块来同步一个对象变量。也可以使用synchronized块来同步类中的静态方法和非静态方法。
synchronized块的语法如下:
public void method()
{
… …
synchronized(表达式)
{
… …
}
}
一、非静态类方法的同步
从《使用Synchronized关键字同步类方法》一文中我们知道使用synchronized关键字来定义方法就会锁定类中所有使用synchronzied关键字定义的静态方法或非静态方法,但这并不好理解。而如果使用synchronized块来达到同样的效果,就不难理解为什么会产生这种效果了。如果想使用synchronized块来锁定类中所有的同步非静态方法,需要使用this做为synchronized块的参数传入synchronized块国,代码如下:
通过synchronized块同步非静态方法
public class SyncBlock
{
public void method1()
{
synchronized(this) // 相当于对method1方法使用synchronized关键字
{
… …
}
}
public void method2()
{
synchronized(this) // 相当于对method2方法使用synchronized关键字
{
… …
}
}
public synchronized void method3()
{
… …
}
}
在上面的代码中的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块同步类方法时应注意。
使用Synchronized块同步方法的更多相关文章
- Java多线程初学者指南(11):使用Synchronized块同步方法
synchronized关键字有两种用法.第一种就是在<使用Synchronized关键字同步类方法>一文中所介绍的直接用在方法的定义中.另外一种就是synchronized块.我们不仅可 ...
- java synchronized静态同步方法与非静态同步方法,同步语句块
摘自:http://topmanopensource.iteye.com/blog/1738178 进行多线程编程,同步控制是非常重要的,而同步控制就涉及到了锁. 对代码进行同步控制我们可以选择同步方 ...
- Java多线程初学者指南(12):使用Synchronized块同步变量
我们可以通过synchronized块来同步特定的静态或非静态方法.要想实现这种需求必须为这些特性的方法定义一个类变量,然后将这些方法的代码用synchronized块括起来,并将这个类变量作为参数传 ...
- 使用Synchronized块同步变量
我们可以通过synchronized块来同步特定的静态或非静态方法.要想实现这种需求必须为这些特定的方法定义一个类变量,然后将这些方法的代码用synchronized块括起来,并将这个类变量作为参数传 ...
- Synchronized块同步变量的误区
我们可以通过synchronized块来同步特定的静态或非静态方法.要想实现这种需求必须为这些特性的方法定义一个类变量,然后将这些方法的代码用synchronized块括起来,并将这个类变量作为参数传 ...
- 用生活例子来解释Java synchronized块
今天满世界的微信小程序的新闻,大家都说对于Android原生程序有构成危险了,我也不想了,以后的事谁知道呢, 我还是好好执行一下今年的计划吧. 项目刚刚上线,最近没啥事,我一直感觉自己的Java基础 ...
- synchronized块中的wait()、nofity()、nofityAll()方法
前言 在Java并发编程实战,会经常遇到多个线程访问同一个资源的情况,这个时候就需要维护数据的一致性,否则会出现各种数据错误,其中一种同步方式就是利用Synchronized关键字执行锁机制,锁机制是 ...
- 线程同步 synchronized 同步代码块 同步方法 同步锁
一 同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块.其语法如下: synchronized(obj){ // ...
- 线程的同步机制:同步代码块&同步方法
解决存在的线程安全问题:打印车票时出现重票,错票 使用同步代码块的解决方案 TestWindow2 package com.aff.thread; /* 使用实现Runnable接口的方式,售票 存在 ...
随机推荐
- SSO系统的实现
当一个网站系统比较大型的时候,我们通常采用面向服务的编程,采用分布式的编程.各个子系统共同来实现一个大的系统,这时候登录注册功能的实现也面临着一些问题. 一.WHAT? SSO是什么? sso是单点登 ...
- Docker下的Spring Cloud三部曲之一:极速体验
版权声明:欢迎转载,请注明出处,谢谢. http://blog.csdn.net/boling_cavalry/article/details/79177930 目录(?)[+] 从本章开始, ...
- SQL Server - 开窗函数
-- 开窗函数:在结果集的基础上进一步处理(聚合操作) SELECT * FROM dbo.Student S# Sname Sage Ssex ---------- ---------- ----- ...
- mongodb 设置用户密码权限
1 设置管理员账户 use admindb.createUser({ user: "useradmin", pwd: "adminpassword", role ...
- Java基础-使用Idea进行远程调试
Java基础-使用Idea进行远程调试 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.
- MySQL数据类型以及基本使用详解
MySQL数据类型以及基本使用详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.MySQL服务器的主要组件 我们知道MySQL的主要组件主要是由服务端(mysqld)和客户端 ...
- shell脚本中自定义日志记录到文件
自定义日志函数和前期变量 # adirname - return absolute dirname of given file adirname() { odir=`pwd`; cd `dirname ...
- [Java] Servlet工作原理之二:Session与Cookie
(未完成) 一.Cookie与Session的使用简介 1 Cookie Cookie 用于记录用户在一段时间内的行为,它有两个版本:Version 0 和 Version 1,分别对应两种响应头 S ...
- 转iOS UIAppearance使用详解
iOS5及其以后提供了一个比较强大的工具UIAppearance,我们通过UIAppearance设置一些UI的全局效果,这样就可以很方便的实现UI的自定义效果又能最简单的实现统一界面风格,它提供如下 ...
- webpack快速入门——CSS进阶:自动处理CSS3前缀
为了浏览器的兼容性,有时候我们必须加入-webkit,-ms,-o,-moz这些前缀.目的就是让我们写的页面在每个浏览器中都可以顺利运行. 1.安装 cnpm i postcss-loader aut ...