详解java修饰符synchronized

来源:互联网 发布:药师丸博子 知乎 编辑:程序博客网 时间:2024/06/06 20:59

synchronized会以两种形式出现在代码中

1.synchronized(对象){}代码块形式

这种形式下,锁是加在括号内的对象上,所以你只需要看括号里面的对象指向的堆内存地址,如果内存地址相同,就会互斥,如果内存地址不同,就可以并发调用。

简单地用代码表示一下:

class Xxx{static String demo = " ";synchronized(demo){}}

对于以上代码,所有xxx类的对象访问的demo都是同一个内存地址:

比如:

Xxx x1 = new Xxx();x1.demo;Xxx x2 = new Xxx();x2.demo;
x1和x2调用的demo其实是同一个,所以当x1调用该代码块时,x2再调用会发现demo上有锁,只能等待x1调用完毕再调用。

class Xxx{String demo = " ";synchronized(demo){}}

相反,如果demo没有static修饰,synchronized锁只会对同一个对象起作用,不同对象可以并发访问。

Xxx x1 = new Xxx();x1.demo;Xxx x2 = new Xxx();x2.demo;
在这几行代码中,x1和x2所调用的demo是分别保存在两个内存地址中,当x1调用synchronized代码块时,x2再调用,会发现,自己的demo上没有锁,所以两个对象可以并发调用。

还有一种特殊情况,synchronized(xxx.class){}这种情况也是对这个类的所有对象起作用的。

2.synchronized 方法名()方法形式

其实修饰方法和代码块形式也是差不多的,如果方法有static修饰,就对该类的所有对象起作用,相反,如果是个动态方法,则只会对同一对象起作用,不同对象可以并发执行。

下面简单叙述一下原理,当有线程执行synchronized代码块时,锁的标志是加在括号内的对象上的。当有线程再调用它时,会检查括号内对象锁的状态,所以当两次调用括号内对象指向不同内存时,是不影响并发执行的。

强调一点,锁加在对象上,只是限制synchronized代码块的调用,不会影响代码块中任何一个变量,对象,以及括号内对象的调用,以及读写操作。


原创粉丝点击