Java类锁和对象锁实践(good)

一、前言

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

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

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

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

二、测试代码。

1.编写一个启动类ObjectLock

Java代码  

  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方法可能会调整以进行不同的测试)

Java代码  

  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,包括各种加锁方法

Java代码  

  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方法修改如下:

Java代码  

  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. }

终端输出如下:

Java代码  

  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方法修改如下:

Java代码  

  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. }

终端输出如下:

Java代码  

  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方法修改如下:

Java代码  

  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. }

终端输出:

Java代码  

  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)都是对当前对象加锁,二者的加锁方法够成了竞争关系,同一时刻只能有一个方法能执行。

时间: 2024-08-01 23:10:44

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

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

Java类锁和对象锁实践 感谢[jiehao]同学的投稿,投稿可将文章发送到[email protected] 类锁和对象锁是否会冲突?对象锁和私有锁是否会冲突?通过实例来进行说明. 一.相关约定 为了明确后文的描述,先对本文涉及到的锁的相关定义作如下约定: 1. 类锁:在代码中的方法上加了static和synchronized的锁,或者synchronized(xxx.class)的代码段,如下文中的increament(): 2.对象锁:在代码中的方法上加了synchronized的锁,或者

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

觉得还不错 留个记录,转载自http://zhh9106.iteye.com/blog/2151791 在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁.线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁.获得内置锁的唯一途径就是进入这个锁的

java 类锁与对象锁(实例锁)同步问题

众所周知,synchronized可修饰方法和代码块,可作用于类或者对象. 当修饰代码块时,synchronized(object) 作用于对象,只约束该对象. synchronized(class)作用于类,约束类所有的对象. 修饰方法时,synchronized 修饰static方法时,作用于类.修饰非static方法时作用于对象. 注意类锁和对象锁是两个不同的锁,二者不会发生同步关系. 由于static变量,可被static方法调用,也可被非static方法调用,当二者同时被synchro

方法锁、对象锁、类锁

对象锁(方法锁),是针对一个对象的,它只在该对象的某个内存位置声明一个标识该对象是否拥有锁,所有它只会锁住当前的对象,一般一个对象锁是对一个非静态成员变量进行synchronized修饰,或者对一个非静态成员方法进行synchronized进行修饰,对于对象锁,不同对象访问同一个被synchronized修饰的方法的时候不会阻塞 类锁是锁住整个类,当有多个线程来声明这个类的对象时候将会被阻塞,直到拥有这个类锁的对象呗销毁或者主动释放了类锁,这个时候在被阻塞的线程被挑选出一个占有该类锁,声明该类的

并发编程大师系列之:Synchronized的类锁和对象锁

说到并发编程,感觉跟大多数人一样,谈之色变,说它简单把,其实很有内容,说难吧,用起来也挺容易,最近我硬着头皮,决心要把并发编程好好的搞一遍.以前,面试的时候,面试官问,并发编程会吗?嗯,接触过,就加一个synchronized关键字就好了,面试官微笑着说,嗯好.特喵的现在感觉来说,这俩low逼.本来写了几行的软文,但感觉在技术文章里面体现,有失风度,明明可以靠文采吃饭,而我却非要靠技术,任性!上代码! 1.对象锁概念: java的所有对象都含有1个互斥锁,这个锁由JVM自动获取和释放.线程进入s

类锁和对象锁,synchronized修饰static方法与非static方法的区别

当synchronized修饰一个static方法时,多线程下,获取的是类锁(即Class本身,注意:不是实例), 作用范围是整个静态方法,作用的对象是这个类的所有对象. 当synchronized修饰一个非static方法时,多线程下,获取的是对象锁(即类的实例对象), 作用范围是整个方法,作用对象          是调用该方法的对象 结论: 类锁和对象锁不同,它们之间不会产生互斥 原文地址:https://www.cnblogs.com/alter888/p/9840402.html

Java 类的定义对象和引用

Java的核心思想万物皆对象. 对象是对属性(成员变量, 静态属性)和方法(函数, 动态属性)的封装 定义一个类 public class 类名{ 成员变量 方法 } 类名   变量名 = new  类名(); 变量名. 面向对象更容易达到一种境界: Reusable(重用性), Extensibility(可扩展性) 面向组件(Component)--比对象更高层次的抽象 WebService 成员变量和局部变量的区别 成员变量可以是java中任意一种数据类型(基础数据类型和引用类型) 成员变

(转)java并发对象锁、类锁、私有锁

转自:http://ifeve.com/java-locks/ 建议参考:http://www.zhihu.com/question/28113814 Java类锁和对象锁实践 感谢[jiehao]同学的投稿,投稿可将文章发送到[email protected] 类锁和对象锁是否会冲突?对象锁和私有锁是否会冲突?通过实例来进行说明. 一.相关约定 为了明确后文的描述,先对本文涉及到的锁的相关定义作如下约定: 1. 类锁:在代码中的方法上加了static和synchronized的锁,或者sync

Java学习(十一):Java锁Synchronized,对象锁和类锁举例

Java的锁分为对象锁和类锁. 1. 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内针对该对象的操作只能有一个线程得到执行.另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块. 2. 然而,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块. 3. 尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对该object中所有其它sync