Java线程同步中关键字synchronized简述

版权声明: https://blog.csdn.net/beiyus/article/details/49124109
Java线程同步中关键字synchronized简述

一、作用:

synchronized关键字通过修饰一个方法或者声明一个代码块,从而产生一个同步对象锁以及对应的同步代码块。每当有线程要对该同步代码块进行访问时,线程就会首先尝试去获取该对象锁,并在成功获取到对象锁后,对该同步代码块进行正常访问,在同步代码块访问过程中,线程会一直持有该对象锁直到同步代码块访问完毕才会释放。在上述线程持有同步锁并进行同步代码块访问过程中,其它线程将无法获得该对象锁,也无法访问该同步代码,这些线程都会被阻塞直到上述线程访问完毕。

synchronized关键字,通过以上措施,确保每次只有一个线程能持有对象锁并对同步代码块进行访问,并在访问结束之前,不会被其它线程访问。也就说,即使同步代码块在执行过程中遭遇线程调度,其它线程也无法访问该同步代码块,直到该线程被重新调度并完成同步代码块的访问并释放对象锁。这样就保证了线程对同步代码块访问的连续性不受线程调度而中断。

二、用法:
synchronized关键字的使用方法有两种:
1、直接在方法前面进行声明,这种方式的声明,整个方法都是同步代码块,至于其对象锁则是访问该方法时所使用的对象也就是this,示例:
class C{
  public synchronized void syncMethod(...){
 ...
  }
}
注:在这种方式的声明中,如果方法前面有static关键字,那么该方法是一个类方法,由于类在Java中其实也是一个class对象,所以类方法的对象锁不是该类的实例化对象,而是该类的class对象。

2、在方法中声明一个同步代码块,这种方式的声明,关键字后{}内的代码块是同步代码块,而其对象锁则是关键字后()内的对象object,示例:

class C{
  public void syncMethod(...){
 ...
 synchronized(object){
    ....
 }
 ...
  }
}
注:在这种方式的声明中,如果object是this,那么它的对象锁和第一种方式的声明是一样的,但是它的同步代码块范围可以更小。

三、死锁
  死锁:当多个线程在执行任务的过程中需要两个或以上的同步资源时,如果某个线程因为部分资源被其它线程占用而只获得了部分资源,并且对这一部分资源进行了保留进入阻塞,同时如果占有其它资源的线程也需要上述线程所占有的资源,并且没有释放自己所占有的资源而进入阻塞,这样就会导致两个或多个阻塞的线程相互等待其它线程的资源,并且由于都不愿先释放自己所占用的资源引起任何线程都无法满足资源要求而被阻塞,最终导致这一系列的线程全部进入阻塞过程,都无法完成任务的执行。上述过程就叫做死锁。

  发生死锁的条件:
  1、多个任务同时执行;
  2、这些任务都需要同时获得两个或以上的不同的同步资源来完成任务,并且这些资源是共享的;
  3、这些线程在获得部分资源后,都不会首先主动释放;
  4、线程获得了部分资源,在等待另一部分资源;另一部分资源被其它线程占用,并且在等待上述线程的资源;

四、其它说明事项:
  1、一个对象的同步对象方法中,可以调用该对象包括该方法本身在内的其它同步方法而不会引起阻塞。
    因为同一对象的所有同步对象方法需要的对象锁都是该对象本身,而对象锁是可以被同一任务多次获取的,或者说该对象锁是可以重入的。因此在同步对象方法内调用该对象的其它同步对象方法可以获得对象锁,而不会被阻塞。
    上述情况成立的条件:1.同一对象;2.对象方法;也就是说不适用于:1.同步类方法,2.不同对象的同步对象方法;
  2、同一对象的所有同步对象方法,在不同的线程中不能被同时执行,也就是说两个线程不能同时执行同一对象的两个相同或者不同的同步对象方法,因为这些方法是共享同一对象锁的,因此当某个线程在执行该对象的某个同步对象方法时,该线程占有该对象锁,其它线程无法获得,也就无法执行该对象的任意同步对象方法了。
  3、如果在同步对象方法中,有对该类其它实例的同步对象方法的引用,那么这两个对象不能在不同的任务中同时以对方为参数执行任务,否则可能会引起死锁;(待推敲)
  4、如果在同步对象方法中,没有对该类其它实例的同步对象方法的引用,或者有引用但不满足第二种情形,那么这两个实例可以在不同的任务中,同时执行这一同步对象方法,而不会出现问题。
  5、同步对象方法中,引用其它类的对象的同步对象方法,可能会引起死锁,也可能不会。。(待推敲)

五、建议:
   1.所有同步方法或代码块内,尽量避免调用其它对象的同步方法。
   2.同步方法被覆写(Override)后,如果覆写后的方法未加synchronized关键字,则该方法不具备同步特征,也就是说,同步属性在覆写后,默认情况下是没有的。
   3.同步的对象锁只能是对象。

参考文章:http://blog.csdn.net/welcome000yy/article/details/8941644
展开阅读全文

没有更多推荐了,返回首页