一、前言

之前对类锁和对象锁是否是互斥的不是太确定,因此决定编写相关的程序进行实践一下。编写前对相关定义约定约定如下:

1. 类锁:在代码中的方法上加了static和synchronized的锁,或者synchronized(xxx.class)的代码段,如下文中的increament();

2.对象锁:在代码中的方法上加了synchronized的锁,或者synchronized(this)的代码段,如下文中的synOnMethod()和synInMethod();

3.私有锁:在类内部声明一个私有属性如private Object lock,在需要加锁的代码段synchronized(lock),如下文中的synMethodWithObj()。

二、测试代码。

1.编写一个启动类ObjectLock

  1. package com.zjh.blog.practice.basic;
  2. public class ObjectLock {
  3. public static void main(String[] args) {
  4. System.out.println("start time = " + System.currentTimeMillis()+"ms");
  5. LockTestClass test = new LockTestClass();
  6. for (int i = 0; i < 3; i++) {
  7. Thread thread = new ObjThread(test, i);
  8. thread.start();
  9. }
  10. }
  11. }

2.编写一个线程类ObjThread,用于启动同步方法(注意它的run方法可能会调整以进行不同的测试)

  1. package com.zjh.blog.practice.basic;
  2. public class ObjThread extends Thread {
  3. LockTestClass lock;
  4. int i = 0;
  5. public ObjThread(LockTestClass lock, int i) {
  6. this.lock = lock;
  7. this.i = i;
  8. }
  9. public void run() {
  10. //无锁方法
  11. //      lock.noSynMethod(this.getId(),this);
  12. //对象锁方法1,采用synchronized synInMethod的方式
  13. lock.synInMethod();
  14. //对象锁方法2,采用synchronized(this)的方式
  15. //      lock.synOnMethod();
  16. //私有锁方法,采用synchronized(object)的方式
  17. //      lock.synMethodWithObj();
  18. //类锁方法,采用static synchronized increment的方式
  19. LockTestClass.increment();
  20. }
  21. }

3.再编写一个锁的测试类LockTestClass,包括各种加锁方法

  1. package com.zjh.blog.practice.basic;
  2. public class LockTestClass {
  3. //用于类锁计数
  4. private static int i = 0;
  5. //私有锁
  6. private Object object = new Object();
  7. /**
  8. * <p>
  9. * 无锁方法
  10. *
  11. * @param threadID
  12. * @param thread
  13. */
  14. public void noSynMethod(long threadID, ObjThread thread) {
  15. System.out.println("nosyn: class obj is " + thread + ", threadId is"
  16. + threadID);
  17. }
  18. /**
  19. * 对象锁方法1
  20. */
  21. public synchronized void synOnMethod() {
  22. System.out.println("synOnMethod begins" + ", time = "
  23. + System.currentTimeMillis() + "ms");
  24. try {
  25. Thread.sleep(2000L);
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. }
  29. System.out.println("synOnMethod ends");
  30. }
  31. /**
  32. * 对象锁方法2,采用synchronized (this)来加锁
  33. */
  34. public void synInMethod() {
  35. synchronized (this) {
  36. System.out.println("synInMethod begins" + ", time = "
  37. + System.currentTimeMillis() + "ms");
  38. try {
  39. Thread.sleep(2000L);
  40. } catch (InterruptedException e) {
  41. e.printStackTrace();
  42. }
  43. System.out.println("synInMethod ends");
  44. }
  45. }
  46. /**
  47. * 对象锁方法3
  48. */
  49. public void synMethodWithObj() {
  50. synchronized (object) {
  51. System.out.println("synMethodWithObj begins" + ", time = "
  52. + System.currentTimeMillis() + "ms");
  53. try {
  54. Thread.sleep(2000L);
  55. } catch (InterruptedException e) {
  56. e.printStackTrace();
  57. }
  58. System.out.println("synMethodWithObj ends");
  59. }
  60. }
  61. /**
  62. * 类锁
  63. */
  64. public static synchronized void <span style="font-size: 1em; line-height: 1.5;">increament</span><span style="font-size: 1em; line-height: 1.5;">() {</span>
  65. System.out.println("class synchronized. i = " + i + ", time = "
  66. + System.currentTimeMillis() + "ms");
  67. i++;
  68. try {
  69. Thread.sleep(2000L);
  70. } catch (InterruptedException e) {
  71. e.printStackTrace();
  72. }
  73. System.out.println("class synchronized ends.");
  74. }
  75. }

三、测试结果

1.测试类锁和对象锁,ObjectThread的run方法修改如下:

  1. public void run() {
  2. //无锁方法
  3. //      lock.noSynMethod(this.getId(),this);
  4. //对象锁方法1,采用synchronized synInMethod的方式
  5. lock.synInMethod();
  6. //对象锁方法2,采用synchronized(this)的方式
  7. //      lock.synOnMethod();
  8. //私有锁方法,采用synchronized(object)的方式
  9. //      lock.synMethodWithObj();
  10. //类锁方法,采用static synchronized increment的方式
  11. LockTestClass.increament();
  12. }

终端输出如下:

  1. start time = 1413101360231ms
  2. synInMethod begins, time = 1413101360233ms
  3. synInMethod ends
  4. class synchronized. i = 0, time = 1413101362233ms
  5. synInMethod begins, time = 1413101362233ms
  6. class synchronized ends.
  7. synInMethod ends
  8. class synchronized. i = 1, time = 1413101364233ms
  9. synInMethod begins, time = 1413101364233ms
  10. class synchronized ends.
  11. synInMethod ends
  12. class synchronized. i = 2, time = 1413101366234ms
  13. class synchronized ends.

可以看到对象锁方法(synInMothod)第一次启动时比类锁方法(increament)快2秒,这是因为在synInMehtod执行时sleep了2秒再执行的increament,而这两个方法共用一个线程,所以会慢2秒,如果increament在run中放到synInMethod前面,那么第一次启动时就是increament快2秒。

   而当类锁方法启动时,另一个线程时的对象锁方法也几乎同时启动,说明二者使用的并非同一个锁,不会产生竞争。
  结论:类锁和对象锁不会产生竞争,二者的加锁方法不会相互影响。
 
  2.私有锁和对象锁,ObjectThread的run方法修改如下:
  1. public void run() {
  2. //无锁方法
  3. //      lock.noSynMethod(this.getId(),this);
  4. //对象锁方法1,采用synchronized synInMethod的方式
  5. lock.synInMethod();
  6. //对象锁方法2,采用synchronized(this)的方式
  7. //      lock.synOnMethod();
  8. //私有锁方法,采用synchronized(object)的方式
  9. lock.synMethodWithObj();
  10. //类锁方法,采用static synchronized increment的方式
  11. //      LockTestClass.increament();
  12. }

终端输出如下:

  1. start time = 1413121912406ms
  2. synInMethod begins, time = 1413121912407ms.
  3. synInMethod ends.
  4. synMethodWithObj begins, time = 1413121914407ms
  5. synInMethod begins, time = 1413121914407ms.
  6. synInMethod ends.
  7. synMethodWithObj ends
  8. synInMethod begins, time = 1413121916407ms.
  9. synMethodWithObj begins, time = 1413121916407ms
  10. synInMethod ends.
  11. synMethodWithObj ends
  12. synMethodWithObj begins, time = 1413121918407ms
  13. synMethodWithObj ends

和类锁和对象锁非常类似。

    结论:私有锁和对象锁也不会产生竞争,二者的加锁方法不会相互影响。
 

3.synchronized直接加在方法上和synchronized(this),ObjectThread的run方法修改如下:

  1. public void run() {
  2. //无锁方法
  3. //      lock.noSynMethod(this.getId(),this);
  4. //对象锁方法1,采用synchronized synInMethod的方式
  5. lock.synInMethod();
  6. //对象锁方法2,采用synchronized(this)的方式
  7. lock.synOnMethod();
  8. //私有锁方法,采用synchronized(object)的方式
  9. //      lock.synMethodWithObj();
  10. //类锁方法,采用static synchronized increment的方式
  11. //      LockTestClass.increament();
  12. }

终端输出:

  1. start time = 1413102913278ms
  2. synInMethod begins, time = 1413102913279ms
  3. synInMethod ends
  4. synInMethod begins, time = 1413102915279ms
  5. synInMethod ends
  6. synOnMethod begins, time = 1413102917279ms
  7. synOnMethod ends
  8. synInMethod begins, time = 1413102919279ms
  9. synInMethod ends
  10. synOnMethod begins, time = 1413102921279ms
  11. synOnMethod ends
  12. synOnMethod begins, time = 1413102923279ms
  13. synOnMethod ends

可以看到,二者严格地串行输出(当然再次执行时先运行synInMethod还是先运行synOnMethod并不是确定的,取决于谁获得了锁)

结论:synchronized直接加在方法上和synchronized(this)都是对当前对象加锁,二者的加锁方法够成了竞争关系,同一时刻只能有一个方法能执行。

Java类锁和对象锁实践(good)的更多相关文章

  1. Java类锁和对象锁实践和内部私有锁关联

    Java类锁和对象锁实践 感谢[jiehao]同学的投稿,投稿可将文章发送到tengfei@ifeve.com 类锁和对象锁是否会冲突?对象锁和私有锁是否会冲突?通过实例来进行说明. 一.相关约定 为 ...

  2. Java类锁和对象锁

    一.类锁和对象锁 二.使用注意 三.参考资料 一.类锁和对象锁 类锁:在代码中的方法上加了static和synchronized的锁,或者synchronized(xxx.class) 对象锁:在代码 ...

  3. java synchronized类锁,对象锁详解(转载)

    觉得还不错 留个记录,转载自http://zhh9106.iteye.com/blog/2151791 在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看 ...

  4. Java锁Synchronized对象锁和类锁区别

    java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁.线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁.获得内置锁的唯一途径就是进入这个锁的保 ...

  5. Java 类锁、对象锁、私有锁

    3.6 Java类锁.对象锁.私有锁.隐式锁 类锁和对象锁是否会冲突?对象锁和私有锁是否会冲突?通过实例来进行说明. 一.相关约定 为了明确后文的描述,先对本文涉及到的锁的相关定义作如下约定: 1. ...

  6. Java的类锁、对象锁和方法锁

    在Java中,对于synchronized关键字,大家看到的第一反应就是这个关键字是进行同步操作的,即得名"同步锁". 当用它来修饰方法和代码块时,默认当前的对象为锁的对象,即对象 ...

  7. java线程同步以及对象锁和类锁解析(多线程synchronized关键字)

    一.关于线程安全 1.是什么决定的线程安全问题? 线程安全问题基本是由全局变量及静态变量引起的. 若每个线程中对全局变量.静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的:若有多个线 ...

  8. Synchronized方法锁、对象锁、类锁区别

    synchronized,这个东西我们一般称之为”同步锁“,他在修饰代码块的时候需要传入一个引用对象作为“锁”的对象. 在修饰方法的时候,默认是当前对象作为锁的对象 在修饰类时,默认是当前类的Clas ...

  9. 类锁、对象锁、互斥锁与synchronized

    本文总结自: https://blog.csdn.net/luckey_zh/article/details/53815694 互斥锁: 若对象有互斥锁,则在任一时刻,只能有一个线程访问对象.类锁.对 ...

随机推荐

  1. chapter 13_3 table访问的元方法

    前两节的算术类.关系类运算符的元方法都为各种错误情况定义了行为,它们不会改变语言的常规行为. 但是Lua还提供了两种可以改变table行为的方法: 一种是查询table中不存在的字段.一种是修改tab ...

  2. 利用POI获取Excel中图片和图片位置

    利用POI获取Excel中图片和图片位置(支持excel2003or2007多sheet) 转自:http://blog.csdn.net/delongcpp/article/details/8833 ...

  3. 监控mysql主从

    这里记录了,每次都百度查询多次. zabbix默认包含mysql监控 其中包含 mysql的基本状态监控 MySQL主从监控需要结合自定义 1)目前项目需求 只对 Slave_IO_Running . ...

  4. WCF部署在IIS上

    WCF部署在IIS上 环境vs2010,WCF应用程序.如何将WCF部署在IIS上. 第一步:右键点击项目,选择生成部署包. 第二步:在你项目所在的文件目录下找到Package文件夹,这就是我们的部署 ...

  5. drupal中安装CKEditor文本编辑器,并配置图片上传功能

    一.下载: 1.CKEditor模块 2.IMCE模块 二.安装       1.复制: 下载完上面两个模块之后,解压,将解压后整个文件夹,复制粘贴,放到 sites\all\modules下面,个人 ...

  6. iOS开发 自定义UIAlertController的样式

    引言: 关于提示框, 系统自带的提示框有时可能满足不了我们的需求, 比如一个提示框的取消按钮我需要灰色字体显示, 这时候就需要自定义提示框的样式了. 示例图 苹果自iOS8开始,就已经废弃了之前用于界 ...

  7. 笔记整理--Linux多线程

    Unix高级环境编程系列笔记 (2013/11/17 14:26:38) Unix高级环境编程系列笔记 出处信息 通过这篇文字,您将能够解答如下问题: 如何来标识一个线程? 如何创建一个新线程? 如何 ...

  8. 你需要简单了解JVM中的内存长什么样子

    下面有关JVM内存,说法错误的是? 1.程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,是线程隔离的 2.Java方法执行内存模型,用于存储局部变量,操作数栈,动态链接 ...

  9. hdu_4718_The LCIS on the Tree(树链剖分+线段树合并)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4718 题意:给你一棵树,每个节点有一个值,然后任给树上的两点,问这两点的最长连续递增区间是多少 题解: ...

  10. nefu 72 N!

    Description Given an integer N(0 ≤ N ≤ 10000), your task is to calculate N! Input One N in one line, ...