java synchronized概念用法

一、概念;

     synchronized是java中的关键字,是一种同步锁。它修饰的对象有一下几种:

     1、修饰一个代码块,被修饰的代码块成为同步语句块,其作用的范围是大括号括起来的代码,作用的对象是调用这个代码块的对象;

     2、修饰一个方法,被修饰的方法成为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;

     3、修饰一个静态方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;

     4、修饰一个类,作用的范围是synchronized后面括号括起来的部分,作用的对象是这个类的所有对象。

     (对象锁:1、2;类锁:3、4)

    修饰一个代码块:

         1、一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程被阻塞。

             如果是多个对象,那么每个对象有一把锁,它们之间是互不影响的。

         2、当一个线程访问对象的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该对象中的非synchronized(this)代码。

         3、给指定的对象加锁synchronized(object),这时,当一个线程访问object对象时,其他试图访问object对象的线程将会阻塞,直到

      该线程访问object对象结束。也就是说谁拿到那个锁,谁就可以运行它所控制的那段代码。

         4、当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的对象来充当锁。

             byte[] lock = new byte[0];

             synchronized(lock){

                //todo 同步代码块

              }

      修饰一个方法:

            1、synchronized修饰一个方法,就是在方法的前面加synchronized关键字,修饰方法和修饰一个代码块类似,只是范围不同。

                修饰代码块范围是大括号括起来的范围,修饰方法范围是整个方法函数。

            2、synchronized关键字不能继承。在子类方法中可以自己加上synchronized关键字,或者调用父类的同步方法。

            3、定义接口方法时不能使用synchronized关键字。

            4、构造方法不能使用synchronized关键字,可以使用synchronized代码块进行同步。

      修饰一个静态方法:

            1、静态方法是属于类的而不属于对象。同样synchronized修饰的静态方法锁定的是这个类的所有对象。   

      修饰一个类:

            1、和修饰一个静态方法一样,锁定得失这个类的所有对象。

      注意点:

            1、无论synchronized关键字加在方法上还是对象上,如果他作用的对象是非静态的,则它是针对对象的锁;如果synchronized作用的是一个静态方法或一个类,则它是针对类的锁,该类的所有对象使用同一把锁。

            2、每个对象只用一个锁与之相关联,谁拿到这个锁谁就可以运行它锁控制的那段代码。

            3、实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以精良避免无用的同步控制。

             

二、静态锁和非静态锁(synchronized与static synchronized)的区别;

      synchronized是对类的当前实例进行加锁,防止其他线程访问该类的该实例的所用synchronized块,注意这里是“类的当前实例”,类的两个不同实例就没有这种约束了。那么static synchronized恰好就是要控制类的所有实例的访问了,static synchronized是限制线程同时访问jvm中该类的所有实例同时访问对应的代码块。实际上,在类中某方法或某代码块中有synchronized,那么在生成一个该类实例后,该类也就有一个监视块,防止线程并发访问该实例synchronized保护块,而static synchronized则是所有该类的实例共用一个监视块了,也就是两个的区别了,也就是synchronized相当于this.synchronized,而static synchronized相当于something.synchronized

 

下面的例子,帮助理解:

pulbic class Something(){  
  
       public synchronized void isSyncA(){}  
  
       public synchronized void isSyncB(){}  
  
       public static synchronized void cSyncA(){}  
  
       public static synchronized void cSyncB(){}  
  
}  

 

假如有Something类的两个实例x与y,那么下列4组组合被1个以上的线程同时访问,是否可行呢?

a.  x.isSyncA()与x.isSyncB()   

b,  x.isSyncA()与y.isSyncA()

c,  x.cSyncA()与y.cSyncB()

d, x.isSyncA()与Something.cSyncA()

分析:

    a:不能同时被访问,因为是同一个实例的synchronized域访问;

    b:可以同时被访问,因为是不同实例访问;

    c:不能同时被访问,因为是静态锁,不同实例之间仍然会被限制;

    d: 可以同时被访问,因为对象所和类锁是分开管理的,互相不限制。

 总结:

A: synchronized static是某个类的范围,synchronized static cSync{}防止多个线程同时访问这个类中的synchronized static 方法。

    它可以对类的所有对象实例起作用。

B: synchronized 是某实例的范围,synchronized isSync(){}防止多个线程同时访问这个实例中的synchronized 方法。

    

参考:

http://blog.csdn.net/luoweifu/article/details/46613015

http://blog.csdn.net/zbuger/article/details/50827762

 

posted @ 2017-06-02 17:59  ≮泛泛之辈┾  阅读(146)  评论(0编辑  收藏  举报