详解java修饰符synchronized

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代码块的调用,不会影响代码块中任何一个变量,对象,以及括号内对象的调用,以及读写操作。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章