【问题描述】关于Java中synchronized 用在实例方法和对象方法上面的区别

【问题分析】大家都知道,在Java中,synchronized 是用来表示同步的,我们可以synchronized 来修饰一个方法(实例方法和类方法---注:不知道这样叫准确不准确,大家理解我的意识就行了)。也可以synchronized 来修饰方法里面的一个语句块。

修饰实例方法:

  1. public synchronized void x() throws InterruptedException
  2. {
  3. ; i++)
  4. {
  5. );
  6. System.out.println("x.......................");
  7. }
  8. }

修饰类方法(static 方法):

  1. public static synchronized void staticX() throws InterruptedException
  2. {
  3. ; i++)
  4. {
  5. );
  6. System.out.println("staticX.......................");
  7. }
  8. }

修饰方法里面语句块:

  1. public static void staticX() throws InterruptedException
  2. {
  3. synchronized (locks)
  4. {
  5. ; i++)
  6. {
  7. );
  8. System.out.println("staticX.......................");
  9. }
  10. }
  11. }

注意:这里不能用synchronized修饰方法外面的语句块(我把他叫做类语句块),虽然我们可以在方法外面定义语句块,这样做会遇到编译错误,这里涉及到了Java里面的对象初始化的部分知识。大概的原因就是synchronized锁住的是对象,当初始化对象的时候,JVM在对象初始化完成之前会调用方法外面的语句块,这个时候对象还不存在,所以就不存在锁了。

那么,在static方法和非static方法前面加synchronized到底有什么不同呢?

大家都知道,static的方法属于类方法,它属于这个Class(注意:这里的Class不是指Class的某个具体对象),那么static获取到的锁,就是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。而非static方法获取到的锁,就是当前调用这个方法的对象的锁了。所以,他们之间不会产生互斥。

看代码:

  1. package com.jack.zhang.chapter9.classlock;
  2. /**
  3. * @author Jack Zhang
  4. * @version vb1.0
  5. * @Email virgoboy2004@163.com
  6. * @Date 2012-5-20
  7. */
  8. public class Test
  9. {
  10. public static synchronized void staticX() throws InterruptedException
  11. {
  12. ; i++)
  13. {
  14. );
  15. System.out.println("staticX.......................");
  16. }
  17. }
  18. public synchronized void x() throws InterruptedException
  19. {
  20. ; i++)
  21. {
  22. );
  23. System.out.println("x.......................");
  24. }
  25. }
  26. public static void main(String[] args)
  27. {
  28. final Test test1 = new Test();
  29. Thread thread = new Thread(new Runnable()
  30. {
  31. public void run()
  32. {
  33. try
  34. {
  35. test1.x();
  36. }
  37. catch (InterruptedException e)
  38. {
  39. // TODO Auto-generated catch block
  40. e.printStackTrace();
  41. }
  42. }
  43. }, "a");
  44. Thread thread1 = new Thread(new Runnable()
  45. {
  46. public void run()
  47. {
  48. try
  49. {
  50. Test.staticX();
  51. }
  52. catch (InterruptedException e)
  53. {
  54. // TODO Auto-generated catch block
  55. e.printStackTrace();
  56. }
  57. }
  58. }, "b");
  59. thread1.start();
  60. thread.start();
  61. }
  62. }

运行结果是:

  1. staticX.......................
  2. x.......................
  3. x.......................
  4. staticX.......................
  5. staticX.......................
  6. x.......................
  7. x.......................
  8. staticX.......................
  9. x.......................
  10. staticX.......................
  11. staticX.......................
  12. x.......................
  13. x.......................
  14. staticX.......................
  15. x.......................
  16. staticX.......................
  17. x.......................
  18. staticX.......................
  19. x.......................
  20. staticX.......................

那当我们想让所有这个类下面的对象都同步的时候,也就是让所有这个类下面的对象共用同一把锁的时候,我们如何办呢?

看代码:

  1. package com.jack.zhang.chapter9.classlock;
  2. /**
  3. * @author Jack Zhang
  4. * @version vb1.0
  5. * @Email virgoboy2004@163.com
  6. * @Date 2012-5-20
  7. */
  8. public class Test
  9. {
  10. ];
  11. public static void staticX() throws InterruptedException
  12. {
  13. synchronized (locks)
  14. {
  15. ; i++)
  16. {
  17. );
  18. System.out.println("staticX.......................");
  19. }
  20. }
  21. }
  22. public void x() throws InterruptedException
  23. {
  24. synchronized (locks)
  25. {
  26. ; i++)
  27. {
  28. );
  29. System.out.println("x.......................");
  30. }
  31. }
  32. }
  33. public static void main(String[] args)
  34. {
  35. final Test test1 = new Test();
  36. final Test test2 = new Test();
  37. Thread thread = new Thread(new Runnable()
  38. {
  39. public void run()
  40. {
  41. try
  42. {
  43. test1.x();
  44. }
  45. catch (InterruptedException e)
  46. {
  47. // TODO Auto-generated catch block
  48. e.printStackTrace();
  49. }
  50. }
  51. }, "a");
  52. Thread thread1 = new Thread(new Runnable()
  53. {
  54. public void run()
  55. {
  56. try
  57. {
  58. Test.staticX();
  59. }
  60. catch (InterruptedException e)
  61. {
  62. // TODO Auto-generated catch block
  63. e.printStackTrace();
  64. }
  65. }
  66. }, "b");
  67. thread1.start();
  68. thread.start();
  69. }
  70. }

运行结果:

  1. staticX.......................
  2. staticX.......................
  3. staticX.......................
  4. staticX.......................
  5. staticX.......................
  6. staticX.......................
  7. staticX.......................
  8. staticX.......................
  9. staticX.......................
  10. staticX.......................
  11. x.......................
  12. x.......................
  13. x.......................
  14. x.......................
  15. x.......................
  16. x.......................
  17. x.......................
  18. x.......................
  19. x.......................
  20. x.......................

http://blog.csdn.net/virgoboy2004/article/details/7585182

Java中synchronized 修饰在static方法和非static方法的区别的更多相关文章

  1. synchronized 修饰在 static方法和非static方法的区别

    Java中synchronized用在静态方法和非静态方法上面的区别 在Java中,synchronized是用来表示同步的,我们可以synchronized来修饰一个方法.也可以synchroniz ...

  2. java——多线程——单例模式的static方法和非static方法是否是线程安全的?

    单例模式的static方法和非static方法是否是线程安全的? 答案是:单例模式的static方法和非static方法是否是线程安全的,与单例模式无关.也就说,如果static方法或者非static ...

  3. static方法和非static方法的区别

    ●生命周期(Lifecycle):静态方法(Static Method)与静态成员变量一样,属于类本身,在类装载的时候被装载到内存(Memory),不自动进行销毁,会一直存在于内存中,直到JVM关闭. ...

  4. RequestDispatcher.forward() 方法和HttpServletResponse.sendRedirect()方法的区别

    RequestDispatcher.forward() 方法和HttpServletResponse.sendRedirect()方法的区别 先贴一段代码 public void logon(Http ...

  5. java static成员变量方法和非static成员变量方法的区别

    这里的普通方法和成员变量是指,非静态方法和非静态成员变量首先static是静态的意思,是修饰符,可以被用来修饰变量或者方法. static成员变量有全局变量的作用       非static成员变量则 ...

  6. Java中使用BufferedReader的readLine()方法和read()方法来读取文件内容

    目标:读文件 编程时,有很多时候需要读取本地文件,下面介绍一下读取方式: 读单行文件 package com; import java.io.*; import java.util.ArrayList ...

  7. length属性,length()方法和size()的方法的区别

    一.java 1.length属性是针对Java中的数组来说的,要求数组的长度可以用其length属性: 2.length()方法是针对字符串来说的,要求一个字符串的长度就要用到它的length()方 ...

  8. View inflate方法和LayoutInflater inflate方法的区别详解

    原创文章,转载请注明出处:http://www.cnblogs.com/baipengzhan/p/6257510.html 我们在Android开发中,对于将布局填充成View对象,最常用的两种办法 ...

  9. length属性、length()方法和size()的方法的区别

    JAVA 1. length属性是针对Java中的数组来说的,要求数组的长度可以用其length属性: 2.length()方法是针对字符串来说的,要求一个字符串的长度就要用到它的length()方法 ...

随机推荐

  1. 记录使用node启用微信公众平台服务器配置

    在微信公众平台的基本信息里面的,修改服务器配置后会有下面的界面. EncodingAESKey是随机生成的,加密方式根据需要自己选择. 关于URL和Token: URL:填写之后会向这个URL发送一个 ...

  2. php中的花括号使用详解

    1.简单句法规则(用花括号界定变量名,适用于PHP所有版本,是php系统设定):    $a = 'flower';    echo "She received some $as" ...

  3. GeneXus笔记本—GeneXusIDE如何切换成中文语言

    嘛 有些人可能比较习惯英文IDE,但是有些人就比较难受 所以为了应对各个地区的差异 GeneXus很人性化的自带了一部分国家的语言包 只不过默认是英文 需要改动一下_(:з」∠)_ 右键你的IDE快捷 ...

  4. php pdo_mysql扩展安装

    本文内容是以 CentOS 为例,红帽系列的 Linux 方法应该都是如此,下面就详细说明步骤,在这里严重鄙视哪些内容??隆⑺档脑悠咴影说挠泄 PDO 编译安装的文章. 1.进入 PHP 的软件包 p ...

  5. Shell07--正则应用

    目录 1. 正则表达式概述 2. 正则表达式规则 3. 正则表达式之GREP文本过滤 4. 正则表达式之SED文本处理 5. 正则表达式之AWK文本处理 1. 正则表达式概述 01. 什么是正则表达式 ...

  6. Oracle 反键索引/反向索引

    反键索引又叫反向索引,不是用来加速数据访问的,而是为了均衡IO,解决热块而设计的比如数据这样: 1000001 1000002 1000005 1000006 在普通索引中会出现在一个叶子上,如果部门 ...

  7. oracle的分析函数over

    参考地址:https://www.cnblogs.com/chinas/p/7058771.html?utm_source=itdadao&utm_medium=referral#_lab2_ ...

  8. .net core 添加NLog

    依赖项——右键——管理NuGet程序包——浏览——输入以下内容 Install-Package NLog.Extensions.Logging -Pre 在根目录下添加nlog.config   更改 ...

  9. office2016pro专业版命令行激活

    1.首先查看Office2016安装目录在哪里,如果是默认安装,没有修改路径,是在C:\Program Files\Microsoft Office\Office16目录下,具体路径还得自行查看,我的 ...

  10. SERVLET API中转发与重定向的区别?

    SERVLET API中转发与重定向的区别? 1.转发(forward方法) 转发仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址. 转发是服务器请求资源,服务器直接访问目标地址的 ...