`
2277259257
  • 浏览: 498464 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java类锁和对象锁实践

 
阅读更多

类锁和对象锁是否会冲突?对象锁和私有锁是否会冲突?通过实例来进行说明。

一、相关约定

为了明确后文的描述,先对本文涉及到的锁的相关定义作如下约定:

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

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

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

 

二、测试代码

1.编写一个启动类ObjectLock

01 public class ObjectLock {
02     public static void main(String[] args) {
03         System.out.println("start time = " + System.currentTimeMillis()+"ms");
04         LockTestClass test = new LockTestClass();
05         for (int i = 0; i < 3; i++) {
06             Thread thread = new ObjThread(test, i);
07             thread.start();
08         }
09     }
10 }

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

01 public class ObjThread extends Thread {
02     LockTestClass lock;
03     int i = 0;
04  
05     public ObjThread(LockTestClass lock, int i) {
06         this.lock = lock;
07         this.i = i;
08     }
09  
10     public void run() {
11         //无锁方法
12 //      lock.noSynMethod(this.getId(),this);
13         //对象锁方法1,采用synchronized synInMethod的方式
14         lock.synInMethod();
15         //对象锁方法2,采用synchronized(this)的方式
16 //      lock.synOnMethod();
17         //私有锁方法,采用synchronized(object)的方式
18 //      lock.synMethodWithObj();
19         //类锁方法,采用static synchronized increment的方式
20         LockTestClass.increment();
21     }
22 }

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

01 public class LockTestClass {
02     //用于类锁计数
03     private static int i = 0;
04     //私有锁
05     private Object object = new Object();
06  
07     /**
08      * &lt;p&gt;
09      * 无锁方法
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     /**
20      * 对象锁方法1
21      */
22     public synchronized void synOnMethod() {
23         System.out.println("synOnMethod begins" + ", time = "
24                 + System.currentTimeMillis() + "ms");
25         try {
26             Thread.sleep(2000L);
27         } catch (InterruptedException e) {
28             e.printStackTrace();
29         }
30         System.out.println("synOnMethod ends");
31     }
32  
33     /**
34      * 对象锁方法2,采用synchronized (this)来加锁
35      */
36     public void synInMethod() {
37         synchronized (this) {
38             System.out.println("synInMethod begins" + ", time = "
39                     + System.currentTimeMillis() + "ms");
40             try {
41                 Thread.sleep(2000L);
42             } catch (InterruptedException e) {
43                 e.printStackTrace();
44             }
45             System.out.println("synInMethod ends");
46         }
47  
48     }
49  
50     /**
51      * 对象锁方法3
52      */
53     public void synMethodWithObj() {
54         synchronized (object) {
55             System.out.println("synMethodWithObj begins" + ", time = "
56                     + System.currentTimeMillis() + "ms");
57             try {
58                 Thread.sleep(2000L);
59             } catch (InterruptedException e) {
60                 e.printStackTrace();
61             }
62             System.out.println("synMethodWithObj ends");
63         }
64     }
65  
66     /**
67      * 类锁
68      */
69     public static synchronized void increament() {
70         System.out.println("class synchronized. i = " + i + ", time = "
71                 + System.currentTimeMillis() + "ms");
72         i++;
73         try {
74             Thread.sleep(2000L);
75         } catch (InterruptedException e) {
76             e.printStackTrace();
77         }
78          System.out.println("class synchronized ends.");
79     }
80  
81 }

三、测试结果

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

01 public void run() {
02         //无锁方法
03 //      lock.noSynMethod(this.getId(),this);
04         //对象锁方法1,采用synchronized synInMethod的方式
05         lock.synInMethod();
06         //对象锁方法2,采用synchronized(this)的方式
07 //      lock.synOnMethod();
08         //私有锁方法,采用synchronized(object)的方式
09 //      lock.synMethodWithObj();
10         //类锁方法,采用static synchronized increment的方式
11         LockTestClass.increament();
12     }

终端输出:

start time = 1413101360231ms
synInMethod begins, time = 1413101360233ms
synInMethod ends
class synchronized. i = 0, time = 1413101362233ms
synInMethod begins, time = 1413101362233ms
class synchronized ends.
synInMethod ends
class synchronized. i = 1, time = 1413101364233ms
synInMethod begins, time = 1413101364233ms
class synchronized ends.
synInMethod ends
class synchronized. i = 2, time = 1413101366234ms
class synchronized ends.

可以看到对象锁方法(synInMothod)第一次启动时比类锁方法(increament)快2秒,这是因为在synInMehtod执行时 sleep了2秒再执行的increament,而这两个方法共用一个线程,所以会慢2秒,如果increament在run中放到 synInMethod前面,那么第一次启动时就是increament快2秒。
而当类锁方法启动时,另一个线程时的对象锁方法也几乎同时启动,说明二者使用的并非同一个锁,不会产生竞争。
结论:类锁和对象锁不会产生竞争,二者的加锁方法不会相互影响。

2.私有锁和对象锁,ObjectThread的run方法修改如下:

01 public void run() {
02         //无锁方法
03 //      lock.noSynMethod(this.getId(),this);
04         //对象锁方法1,采用synchronized synInMethod的方式
05         lock.synInMethod();
06         //对象锁方法2,采用synchronized(this)的方式
07 //      lock.synOnMethod();
08         //私有锁方法,采用synchronized(object)的方式
09         lock.synMethodWithObj();
10         //类锁方法,采用static synchronized increment的方式
11 //      LockTestClass.increament();
12     }

终端输出:

start time = 1413121912406ms
synInMethod begins, time = 1413121912407ms.
synInMethod ends.
synMethodWithObj begins, time = 1413121914407ms
synInMethod begins, time = 1413121914407ms.
synInMethod ends.
synMethodWithObj ends
synInMethod begins, time = 1413121916407ms.
synMethodWithObj begins, time = 1413121916407ms
synInMethod ends.
synMethodWithObj ends
synMethodWithObj begins, time = 1413121918407ms
synMethodWithObj ends

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

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

3.synchronized直接加在方法上和synchronized(this)ObjectThread的run方法修改如下:
public void run() {
		//无锁方法
//		lock.noSynMethod(this.getId(),this);
		//对象锁方法1,采用synchronized synInMethod的方式
		lock.synInMethod();
		//对象锁方法2,采用synchronized(this)的方式
		lock.synOnMethod();
		//私有锁方法,采用synchronized(object)的方式
//		lock.synMethodWithObj();
		//类锁方法,采用static synchronized increment的方式
//		LockTestClass.increament();
	}

终端输出:

start time = 1413102913278ms
synInMethod begins, time = 1413102913279ms
synInMethod ends
synInMethod begins, time = 1413102915279ms
synInMethod ends
synOnMethod begins, time = 1413102917279ms
synOnMethod ends
synInMethod begins, time = 1413102919279ms
synInMethod ends
synOnMethod begins, time = 1413102921279ms
synOnMethod ends
synOnMethod begins, time = 1413102923279ms
synOnMethod ends

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

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

分享到:
评论

相关推荐

    Java SE实践教程 源代码 下载

    6.2.2 锁对象 120 6.2.3 Condition对象 121 6.2.4 再谈synchronized 122 6.3 协调任务 124 6.3.1 线程池和Executor 124 6.3.2 Callable和Future 126 6.3.3 ScheduledExecutorService 127 6.4 线程安全的集合...

    Java SE实践教程 pdf格式电子书 下载(四) 更新

    6.2.2 锁对象 120 6.2.3 Condition对象 121 6.2.4 再谈synchronized 122 6.3 协调任务 124 6.3.1 线程池和Executor 124 6.3.2 Callable和Future 126 6.3.3 ScheduledExecutorService 127 6.4 线程安全的集合...

    java 并发编程实践 001

    java 并发编程实践001 002 两个文件全部下载后 用 7z解压 第1章 介绍 1.1 并发的(非常)简短历史 1.2 线程的优点 1.3 线程的风险 1.4 线程无处不在 第1部分 基础 第2章 线程安全 2.1 什么是线程安全性 2.2 原子...

    Java并发编程实践 PDF 高清版

    Java 5以及6在开发并发程序取得了显著的进步,提高了Java虚拟机的性能,提高了并发类的可伸缩性,并加入了丰富的新并发构建块。在本书中,这些便利工具的创造者不仅解释了它们究竟如何工作、如何使用,同时,还阐释...

    JAVA并发编程实践_中文版(1-16章全)_1/4

    真正的Addison-Wesley 出品的Java Concurrency in Practice 中文版 目录回到顶部↑ 代码清单 序 第1章 介绍 1.1 并发的(非常)简短历史 1.2 线程的优点 1.3 线程的风险 1.4 线程无处不在 第1部分 基础 第2章 线程...

    Java SE实践教程 pdf格式电子书 下载(一) 更新

    6.2.2 锁对象 120 6.2.3 Condition对象 121 6.2.4 再谈synchronized 122 6.3 协调任务 124 6.3.1 线程池和Executor 124 6.3.2 Callable和Future 126 6.3.3 ScheduledExecutorService 127 6.4 线程安全的集合...

    深入Java虚拟机(原书第2版).pdf【附光盘内容】

    20.2 对象锁 20.3 指令集中对同步的支持 20.3.1 同步语句 20.3.2 同步方法 20.4 object类中的协调支持 20.5 随书光盘 20.6 资源页 附录a 按操作码助记符排列的指令集 附录b 按功能排列的操作码助记...

    Java并发编程实践part1

    中文完整版的Java并发编程实践PDF电子书 作者:Brian Gogetz Tim Peierls Joshua Bloch Joseph Bowbeer David Holmes Doug Lea 译者:韩锴 方秒 目录 第1章 介绍 1.1 并发的(非常)简短历史 1.2 线程的优点 1.3 ...

    最新Java面试题视频网盘,Java面试题84集、java面试专属及面试必问课程

    │ Java面试题20.jsp和Servlet的相同点和不同点?.mp4 │ Java面试题21.内置对象和四大作用域和页面传值.mp4 │ Java面试题22.Session和Cookie的区别.mp4 │ Java面试题23.mvc模式和mvc各部分的实现.mp4 │ Java面试...

    深入理解_Java_虚拟机 JVM_高级特性与最佳实践

    / 112 5.2.5 服务器JVM进程崩溃 / 113 5.3 实战:Eclipse运行速度调优 / 114 5.3.1 调优前的程序运行状态 / 114 5.3.2 升级JDK 1.6的性能变化及兼容问题 / 117 5.3.3 编译时间和类加载时间的优化 / 122 5.3.4 ...

    Java理论与实践:Mustang中的同步优化

    当两个线程都想访问共享的易变变量时,这两个线程不仅必须使用同步,而且如果它们正在使用synchronized块,那么这些synchronized 块还必须使用同一个锁对象。本文还介绍了JVM对于竞争锁请求和非竞争锁请求有不同的...

    Java并发编程全套源码

    Java并发编程全套源码,涵盖常见并发编程常见的所有知识点,如对象锁,Executors多任务线程框架,线程池等代码示例.

    Java超神之路.rar

    2.多线程并发编程,现在并发几乎是写服务端程序必须的技术,那对Java中的多线程就要有足够的熟悉,包括对象锁机制、synchronized关键字,concurrent包都要非常熟悉,这部分推荐你看看《Java并发编程实践》这本书,...

    Java虚拟机

    5.3.3 编译时间和类加载时间的优化 5.3.4 调整内存设置控制垃圾收集频率 5.3.5 选择收集器降低延迟 5.4 本章小结 第三部分 虚拟机执行子系统 第6章 类文件结构 6.1 概述 6.2 无关性的基石 6.3 Class类文件...

    Java 性能优化实战 21 讲2021年

    │ 10 案例分析:大对象复用的目标和注意点.mp4 │ 11 案例分析:如何用设计模式优化性能.mp4 │ 12 案例分析:并行计算让代码“飞”起来.mp4 │ 14 案例分析:乐观锁和无锁.mp4 │ 16 案例分析:常见 Java ...

    Java并发编程part2

    中文完整版的Java并发编程实践PDF电子书 作者:Brian Gogetz Tim Peierls Joshua Bloch Joseph Bowbeer David Holmes Doug Lea 译者:韩锴 方秒 目录 第1章 介绍 1.1 并发的(非常)简短历史 1.2 线程的优点 1.3 ...

    concurrent 多线程 教材

    23 IBM 的 Java 诊断,第 3 部分 使用面向 Java 的 Lock Analyzer 诊断同步和锁问题.mht 24 实现 Java 多线程并发控制框架.mht 25 多线程、多平台环境中的跟踪.mht 26 使用 ConTest 进行多线程单元测试.mht 27 ...

    Java性能优化实战视频全集

    10 案例分析:大对象复用的目标和注意点.mp4 11 案例分析:如何用设计模式优化性能.mp4 12 案例分析:并行计算让代码“飞”起来.mp4 13 案例分析:多线程锁的优化.mp4 14 案例分析:乐观锁和无锁.mp4 15 案例...

Global site tag (gtag.js) - Google Analytics