Java的最基本的同步方式,即使用synchronized关键字来控制一个方法的并发访问。 每一个用synchronized关键字声明的方法都是临界区。在Java中,同一个对象的临界区,在同一时间只有一个允许被访问。

静态方法则有不同的行为。用synchronized关键字声明的静态方法,同时只能够被一个执行线程访问,但是其他线程可以访问这个对象的非静态的synchronized方法。必须非常谨慎这一点,因为两个线程可以同时访问一个对象的两个不同的synchronized方法,即其中一个是静态synchronized方法,另一个是非静态synchronized方法。如果两个方法都改变了相同的数据,将会出现数据不一致的错误。

synchronized块的语法如下:

public void method()

{

synchronized(表达式)

{

}

}

synchronized关键字有两种用法,一种是只用于方法的定义中,另外一种是synchronized块,我们不仅可以使用synchronized来同步一个对象变量,你也可以通synchronizedl来同步类中的静态方法和非静态方法。

第一种:非静态方法的同步从java相关语法可以知道使用synchronized关键字来定义方法就会锁定类中所用使用synchroniezd关键字定义的静态方法和非静态方法,但是这有点不好理解,如果要synchronized块,来达到这样的效果,就不难理解为什么会产生这种效果了,如果使用synchronized来锁定类中所有的同步非静态方法,只需要使用this作为synchronized块的参数传入synchronized块中,代码如下:

public class Test

{

public void method1()

{

synchronized(this)

{

}

}

public synchronized void method2()

{

}

}

public class Test

{

public void method1()

{

synchronized(this)

{

}

}

public synchronized void method2()

{

}

}

在上面的代码中的method1使用了synchronized块,method2方法是用了synchronized关键字来定义方法,如果使用同一个Test实例时,这两个方法只要有一个在执行,其他的方法都会因未获得同步锁而被堵塞。除了使用this作为synchronized块的参数,也可以使用Test.this作为synchronized块的参数来达到同样的效果。

在内类中使用synchronized块中,this只表示内类,和外类(OuterClass)没有关系。但是内类中的非静态方法和外类的非静态方法也可以同步。如果在内类中加个方法method3也可以使和Test里面的2个方法同步,代码如下:

public class Test

{

class InnerClass

{

public void method3()

{

synchronized(Test.this){

}

}

}

}

public class Test

{

class InnerClass

{

public void method3()

{

synchronized(Test.this){

}

}

}

}

上面InnerClass的method3方法与Test的method1和method2方法在同一时间内只能有一个方法执行。

synchronized块不管是正确执行完,还是因为程序出错因异常退出synchronized块,当前的synchronized块所持有的同步锁都会自动释放,因此在使用synchronized块不必担心同步锁的问题。

二、静态方法的同步由于在调用静态方法时,对象实例不一定被创建,因此,就不能使用this来同步静态方法,而必须使用Class对象来同步静态方法。代码如下:

public class Test{

pubic static void method1(){

synchronized(Test.class){

}

}

public static synchronized void method2(){

}

}

public class Test{

pubic static void method1(){

synchronized(Test.class){

}

}

public static synchronized void method2(){

}

}

在同步静态方法时可以使用类的静态字段class来得到class对象,在上例中method1和method2方法只有一个方法执行,除了使用class字段可以得到class对象,还可以通过实例的getClass()方法获取class对象,代码如下:

public class Test{

public static Test test;

public Test(){

test=this;

}

public static void method1(){

synchronized(test.getClass()){

}

}

}

public class Test{

public static Test test;

public Test(){

test=this;

}

public static void method1(){

synchronized(test.getClass()){

}

}

}

在上面的代码中,我们通过一个public的静态对象得到Test的一个实例,并通过这个实例的getClass方法获取一个class对象(注意一个类的所有实例通过getClass方法得到的都是同一个Class对象)。我们也可以通过class使不同类的静态方法同步,代码如下:

public class Test1{

public static void method1(){

synchronized(Test.class){

}

}

}

public class Test1{

public static void method1(){

synchronized(Test.class){

}

}

}

注意:在使用synchronized块来同步方法时,非静态方法可以通过this来同步,而静态方法必须使用class对象来同步,但是非静态方法也可以通过使用class来同步静态方法。但是静态方法中不能使用this来同步非静态方法。这点在使用synchronized块需要注意。

Notesynchronized关键字会降低应用程序的性能,因此只能在并发情景中需要修改共享数据的方法上使用它。如果多个线程访问同一个synchronized方法,则只有一个线程可以访问,其他线程将等待。如果方法声明没有使用synchronized关键字,所有的线程都能在同一时间执行这个方法,因而总运行时间降低。如果已知一个方法不会被一个以上线程调用,则无需使用synchronized关键字声明之。

可以递归调用被synchronized声明的方法。当线程访问一个对象的同步方法时,它还可以调用这个对象的其他的同步方法,也包含正在执行的方法,而不必再次去获取这个方法的访问权。

我们可以通过synchronized关键字来保护代码块(而不是整个方法)的访问。应该这样利用synchronized关键字:方法的其余部分保持在synchronized代码块之外,以获取更好的性能。临界区(即同一时间只能被一个线程访问的代码块)的访问应该尽可能的短。例如在获取一幢楼人数的操作中,我们只使用synchronized关键字来保护对人数更新的指令,并让其他操作不使用共享数据。当这样使用synchronized关键字时,必须把对象引用作为传入参数。同一时间只有一个线程被允许访问这个synchronized代码。通常来说,我们使用this关键字来引用正在执行的方法所属的对象:

synchronized(this){

//Java code

}

java同步关键字_Java中synchronized关键字修饰方法同步的用法详解相关推荐

  1. java metadata 使用_java 查询oracle数据库所有表DatabaseMetaData的用法(详解)

    一 . 得到这个对象的实例 Connection con ; con = DriverManager.getConnection(url,userName,password); DatabaseMet ...

  2. java正则 环视_Java正则环视和反向引用功能与用法详解

    本文实例讲述了Java正则环视和反向引用功能与用法.分享给大家供大家参考,具体如下: 环视 1.环视概念 环视,又称为零宽断言,简称断言. 环视强调位置(前面或后面),必须匹配环视表达式,才能匹配成功 ...

  3. revoke mysql_浅谈MySQL中授权(grant)和撤销授权(revoke)用法详解

    MySQL 赋予用户权限命令的简单格式可概括为: grant 权限 on 数据库对象 to 用户 一.grant 普通数据用户,查询.插入.更新.删除 数据库中所有表数据的权利 grant selec ...

  4. mysql revoke 授权_浅谈MySQL中授权(grant)和撤销授权(revoke)用法详解

    MySQL 赋予用户权限命令的简单格式可概括为: grant 权限 on 数据库对象 to 用户 一.grant 普通数据用户,查询.插入.更新.删除 数据库中所有表数据的权利 grant selec ...

  5. Python中第三方库Requests库的高级用法详解

    Python中第三方库Requests库的高级用法详解 虽然Python的标准库中urllib2模块已经包含了平常我们使用的大多数功能,但是它的API使用起来让人实在感觉不好.它已经不适合现在的时代, ...

  6. 信息学奥赛 python 教程_Python在信息学竞赛中的运用及Python的基本用法(详解)

    前言 众所周知,Python是一种非常实用的语言.但是由于其运算时的低效和解释型编译,在信息学竞赛中并不用于完成算法程序.但正如LRJ在<算法竞赛入门经典-训练指南>中所说的一样,如果会用 ...

  7. python调用包中的方法_python 中不同包 类 方法 之间的调用详解

    目录结构如下: 在hello.py中导入ORM.py这个文件的时候,采用 import ORMPackage.ORM 或者 import ORM u = User(id = 123, name='co ...

  8. mysql isnull()_MySql中的IFNULL、NULLIF和ISNULL用法详解

    今天用到了MySql里的isnull才发现他和MSSQL里的还是有点区别,现在简单总结一下: mysql中isnull,ifnull,nullif的用法如下: isnull(expr) 的用法: 如e ...

  9. JAVA中希尔排序去的讲解_java 中基本算法之希尔排序的实例详解

    java 中基本算法之希尔排序的实例详解 希尔排序(Shell Sort)是插入排序的一种.也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本.希尔排序是非稳定排序算法.该方法因DL.Shel ...

最新文章

  1. GNU make manual 翻译(六十九)
  2. 动态代理之Rxjava/Retrofit应用实战
  3. java static关键字_好程序员Java教程分享static关键字的理解
  4. 360浏览器兼容模式下IE内核版本
  5. invalid substring parameter in My Opportunity account determination
  6. 两个链表求交集_实现两个排序链表的并集和交集
  7. html3d变形,深入理解CSS变形transform(3d) - 小火柴的蓝色理想
  8. m126a linux驱动下载,hpm126a驱动下载
  9. INTEL 傲腾16G 的再利用
  10. python卸载pip_python 怎样卸载pip
  11. 沃趣陈栋ORACLE认证,QData-Oracle-数据库一体机---沃趣科技.pdf
  12. 如何删除Win10“此电脑”中多出的“CD驱动器”盘符
  13. 服务器系统部署方案,系统部署方案.doc
  14. 【PHP】安装phpoffice/phpspreadsheet环境OneinStack安装ext-fileinfo这个扩展
  15. 常见的agv控制系统及功能有哪些?
  16. 总结定时器设计方法_超实用!网站导航栏设计方法总结
  17. 浙江电信IPTV+上网 Padavan老毛子固件单线复用
  18. IDEA 2019注册码(激活码)
  19. substr函数c语言实现,substr是什么函数?怎么用
  20. 基于贝叶斯算法文本分析之新闻分类

热门文章

  1. java wait 线程安全吗_Java多线程中的wait与notify
  2. java ipv6正则表达式_IPV4和IPV6正则表达式的深入讲解
  3. 深度学习 dns tunnel检测 使用统计特征 全连接网络——精度99.8%
  4. 乐视云监控数据存放到influxdb中
  5. cassandra框架模型之一——Colum排序,分区策略 Token,Partitioner bloom-filter,HASH
  6. JD AWS vue上传文件
  7. linux 查找大文件
  8. Spring Boot 的配置文件
  9. Spark 1.6.2 + Beam 2.0.0读取Mongodb数据进行相应逻辑处理
  10. INPUT type=password 元素 | input type=password 对象