一、前言

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

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. 希望获取到页面中所有的checkbox怎么做?

    var domList = document.getElementsByTagName(‘input’); var checkBoxList = []; var len = domList.lengt ...

  2. linux服务器的操作禁忌

    1.linux系统是否支持开启SELINUX服务 我方linux系统的服务器不支持开启Selinux服务,如果开启了selinux服务,会导致系统异常并无法启动. 2.linux系统下能否开启NetW ...

  3. 第2章 熟悉Eclipse开发工具----加减乘除,和差积商的英文写法

    加减乘除表示运算:plus  minus multiply divide和差积商表示运算结果:sum difference product quotient

  4. 将数组写入plist文件

    data 加载plist [NSBundle mainBundle] [arr writeToURL:<#(NSURL *)#> atomically:<#(BOOL)#>]

  5. smartGit注意点

    1.xcode工程默认会创建一个.git文件,去掉勾选 2.文件夹不显示,点击smartGit导航栏上的view-->Files from Subdirectories

  6. JavaScript “类”定义 继承 闭包 封装

    一.Javascript “类”: 类:在面向对象编程中,类(class)是对象(object)的模板,定义了同一组对象(又称"实例")共有的属性和方法. Javascript是一 ...

  7. jQuery实现的简单分页功能的详细解析

    分页功能在项目开发中不可或缺,老司机操作起来就和呼吸一样简单,新手恐怕就会吃力一些. 今天我回顾了一下具体的操作步骤,决定详细的分析一下每一步的实现目的及原理. 我们会创建一个简单的json文件来模拟 ...

  8. POJ 1258 Agri-Net(Prim)

    ( ̄▽ ̄)" #include<iostream> #include<cstdio> #include<cmath> #include<algori ...

  9. Mysql 锁机制

    innodb引擎提供了针对表级锁和行级锁 这个文章说的是行级锁 Lock有两种类型: 1,s-lock(共享锁),拥有该锁的transaction可以对row进行read操作 2,x-lock(排它锁 ...

  10. eclipse安卓引入库项目的正确方法

    之前清单文件里theme主题老是改不成库项目里定义好的主题@style/Theme.AppCompat.Light,只能用默认主题@style/AppTheme <application and ...