JAVA多线程-对象及变量的并发访问(一)synchronized详解
2016-02-20 09:07
519 查看
一、synchronized同步方法
1.1 方法内的变量为线程安全
非线程安全的问题存在于“实例变量”中,如果是方法内部的私有变量,则不存在“非线程安全”问题,所得结果也就是“线程安全”的了。
1.2 实例变量非线程安全
如果多个线程共同访问1个对象中的实例变量,则有可能出现“非线程安全”问题。
1.3 多个对象多个锁
synchronized关键字添加到方法上,取得的锁是对象锁,而不是把一段代码或方法当作锁。如果多个线程访问多个对象,则JVM就会创建多个锁。
1.4 synchronized方法与锁对象
调用关键字synchronized声明的方法,一定是排队运行的。另外需要牢牢记住“共享”两个字,只有共享资源的读写访问才需要同步化,如果不是共享资源,那么根本就没有同步的必要。
结论:
(一)A线程先持有Object对象的Lock锁,B线程可以以异步的方式调用Object对象中的非synchronized类型的方法。
(二)A线程先持有Object对象的Lock锁,B线程如果在这时调用Object对象中的synchronized类型的方法则需等待,也就是同步。
1.5 synchronized锁重入
关键字synchronized拥有锁重入的功能,也就是在使用synchronized时,当一个线程得到一个对象锁后,再次请求此对象锁时是可以在得到该对象的锁 的。这也证明在一个synchronized方法/块的内部调用本类的其他synchronized方法/块时,是可以永远得到锁的。
1.6 出现异常,锁自动释放
1.7 同步不具有继承性
二、synchronized同步语句块
[b]2.1 synchronized的弊端
[/b]
用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法执行一个长时间的任务,那么B线程必须等待比较长时间。这样的情况下可以使用synchronized同步语句块来解决。synchronized方法是对当前对象进行加锁,而synchronized代码块是对某一个对象进行加锁。
2.2 synchronized同步代码块的使用
当一个线程访问object的一个synchronized同步代码块时,另一个线程仍然可以访问该object对象中的非synchronized同步代码块。
2.3 静态同步synchronized方法与synchronized(class)代码块
(这个比较重要,面试问题中常遇到的问题)
关键字synchronized还可以应用在static静态方法上,如果这样写,那是对当前的*.java文件对应的Class类进行持锁。在static静态方法上直接添加synchronized关键字与局部代码块添加(类名.class)的作用是一致的。
区别:关键字加到static静态方法上是给Class类上锁,而加到非static静态方法上是给对象上锁。
2.4 数据类型的String的常量池特性
由于常量池具有缓存的功能,所以两个线程中两个锁的锁对象是同一个字符串时,会导致线程同步。也就是一个线程拿到锁,另一个线程堵塞。结论:一般不会使用字符串当作锁对象。
2.5 锁对象的改变
在将任何数据类型作为同步锁时,需要注意的是,是否有多个线程同时持有锁对象,如果同时持有相同的锁对象,则这些线程之间就是同步的;如果分别获得锁对象,这些线程之间就是异步的。
还需要提示一下,只要对象不变,即时对象的属性被改变,运行的结果还是同步。
1.1 方法内的变量为线程安全
非线程安全的问题存在于“实例变量”中,如果是方法内部的私有变量,则不存在“非线程安全”问题,所得结果也就是“线程安全”的了。
1.2 实例变量非线程安全
如果多个线程共同访问1个对象中的实例变量,则有可能出现“非线程安全”问题。
1.3 多个对象多个锁
synchronized关键字添加到方法上,取得的锁是对象锁,而不是把一段代码或方法当作锁。如果多个线程访问多个对象,则JVM就会创建多个锁。
1.4 synchronized方法与锁对象
调用关键字synchronized声明的方法,一定是排队运行的。另外需要牢牢记住“共享”两个字,只有共享资源的读写访问才需要同步化,如果不是共享资源,那么根本就没有同步的必要。
结论:
(一)A线程先持有Object对象的Lock锁,B线程可以以异步的方式调用Object对象中的非synchronized类型的方法。
(二)A线程先持有Object对象的Lock锁,B线程如果在这时调用Object对象中的synchronized类型的方法则需等待,也就是同步。
1.5 synchronized锁重入
关键字synchronized拥有锁重入的功能,也就是在使用synchronized时,当一个线程得到一个对象锁后,再次请求此对象锁时是可以在得到该对象的锁 的。这也证明在一个synchronized方法/块的内部调用本类的其他synchronized方法/块时,是可以永远得到锁的。
1.6 出现异常,锁自动释放
1.7 同步不具有继承性
二、synchronized同步语句块
[b]2.1 synchronized的弊端
[/b]
用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法执行一个长时间的任务,那么B线程必须等待比较长时间。这样的情况下可以使用synchronized同步语句块来解决。synchronized方法是对当前对象进行加锁,而synchronized代码块是对某一个对象进行加锁。
2.2 synchronized同步代码块的使用
当一个线程访问object的一个synchronized同步代码块时,另一个线程仍然可以访问该object对象中的非synchronized同步代码块。
2.3 静态同步synchronized方法与synchronized(class)代码块
(这个比较重要,面试问题中常遇到的问题)
关键字synchronized还可以应用在static静态方法上,如果这样写,那是对当前的*.java文件对应的Class类进行持锁。在static静态方法上直接添加synchronized关键字与局部代码块添加(类名.class)的作用是一致的。
区别:关键字加到static静态方法上是给Class类上锁,而加到非static静态方法上是给对象上锁。
2.4 数据类型的String的常量池特性
由于常量池具有缓存的功能,所以两个线程中两个锁的锁对象是同一个字符串时,会导致线程同步。也就是一个线程拿到锁,另一个线程堵塞。结论:一般不会使用字符串当作锁对象。
2.5 锁对象的改变
在将任何数据类型作为同步锁时,需要注意的是,是否有多个线程同时持有锁对象,如果同时持有相同的锁对象,则这些线程之间就是同步的;如果分别获得锁对象,这些线程之间就是异步的。
还需要提示一下,只要对象不变,即时对象的属性被改变,运行的结果还是同步。
相关文章推荐
- Elasticsearch 2.2.0 JAVA开发篇:搜索操作
- Struts2--中文问题
- Java IO 装饰者模式
- Struts2--ModelDriven接收参数
- Struts2--DomainModel接收参数---使用广泛!!!
- javaji基础x2
- Struts2--Action属性接收参数
- JAVA的包装类
- MAC 下写 Java I/O 流
- Spring ioc架构
- 深入浅出Java回调机制 / 回掉函数 / 深入浅出理解 Java回调机制(异步) GOOD
- javascrpt构建实用的类工厂
- 分组校验和的java实现
- mysql-connector-java-5.0.3-bin.jar中的Preparedstatement居然没有isClosed()方法
- java:使用匿名类直接new接口 或者 new类
- 异常java.lang.IllegalStateException的解决
- 【慕课笔记】第一章 异常与异常处理 第5节 JAVA中的异常链
- Java学习之DAO设计模式
- java swing 音乐播放器-乐乐音乐
- 4个理由告诉你Java为何排行第一