用关键字synchronized声明方法是有弊端的。java
synchronized同步代码块的使用:当两个并发线程访问桶一个对象object中的synchronized(this)同步代码块是,一段时间内只能有一个线程被执行,另外一个线程必须等待当前线程执行完这个代码块之后才能执行该代码块。缓存
synchronized(this){ }
当一个线程访问object的一个synchronized同步代码块时,另外一个线程仍然能够访问该object对象中的非synchronized(this)同步代码块。所以能够较同步方法提升效率。多线程
object对象中的代码,不在synchronized块中就是异步执行,在synchronized块中就是同步执行。并发
synchronized代码块之间的同步性:在使用synchronized(this)同步代码块时须要注意的是,当一个线程访问object的一个synchronized(this)同步代码块时,其余线程对同一个object中全部其余synchronized(this)同步代码块的访问将被阻塞,这说明synchronized使用的对象监视器是同一个。必须等待当前synchronized(this)同步代码块执行完以后,才能访问其余的synchronized(this)同步代码块。异步
同synchronized方法同样,synchronized(this)同步代码块也是锁定当前对象的。工具
将任意对象做为对象监视器this
6.1 多个线程调用同一个对象的不一样名称的synchronized同步方法或synchronized(this)同步代码块是,调用的效果就是按顺序执行,同步的,阻塞的。线程
6,2 synchronized代码块支持对任意对象做为对象监视器来实现同步的功能,大可能是实例变量及方法参数。使用方法为synchronized(非this对象 x){}code
在多个线程持有的对象监视器为同一个对象的前提下,同一时间只有一个线程能够执行synchronized(非this对象 x)同步代码块中的代码。对象
6.3 锁非this对象具备好处:synchronized(非this对象)同步代码块与同步方法和synchronized(this)同步代码块是异步的,不会与其余锁this同步方法争抢this锁,则可大大提升运行效率。
6.4 使用synchronized(非this对象)同步代码块进行同步操做时,对象监视器必须是同一个对象,不然就有多把锁,结果为异步运行。
6.5使用synchronized(非this对象)同步代码块能够避免脏读问题。
synchronized(非this对象 x)同步代码块是将x对象自己做为“对象监视器”,这样就有如下三个结论:
1)当多个线程同时执行synchronized(x)同步代码块时呈同步效果;
2)当其余线程执行x对象中的synchronized同步方法时呈同步效果;
3)当其余线程执行x对象方法里的synchronized(this)代码块时也呈同步效果。
静态同步synchronized方法与synchronized(class)代码块
关键字synchronized能够应用在static静态方法上,即对当前的*.Java文件对应的Class类进行持锁。synchronized关键字加到静态方法上是给Class类上锁,而synchronized关键字加到非static方法上是给对象上锁。
Class锁能够对类的全部对象实例起做用。
同步synchronized(class)代码块与synchronized static方法的做用同样。synchronized(Service。class)。
数据类型String的常量池特性
1)在JVM中具备常量缓存池的功能
String a = "A"; String b = "A"; System.out.println(a == b); 输出结果为:true
将synchronized(string)同步块与String联合使用时,要注意常量池带来的一些例外。如线程A和线程B持有的锁都是“aa”,因为“aa”的缓存池属性,他们持有的是同一个锁,因此有可能其中一个线程永远没法执行。
多线程的死锁
死锁:不一样的线程都在等待根本不愿被释放的锁,从而致使全部的任务都没法继续完成。
public void run(){ if(username.equals("a")){ synchronized(lock1){ //todo synchronized(lock2){ //todo } } } if(username.equals("b")){ synchronized(lock2){ //todo synchronized(lock1){ //todo } } } }
可使用JDK自带的工具来检测是否有死锁的现象:1)jps--查询出线程id号;2)jstack -l 线程id号 --列出Java stack信息。
内置类与静态内置类
1)内置类中有两个同步方法,但使用不一样的锁,则运行结果是异步的。
锁对象的改变
在将任何数据类型做为同步锁时,须要注意的是,是否有多个线程同时持有锁对象,若是同时持有相同的锁对象,那么这些线程之间就是同步的,若是分别得到锁对象,这些线程之间就是异步的。
只要对象不变,即便对象的属性被改变,运行的结果仍是同步的。