您的位置:首页 > 编程语言 > Java开发

Java多线程与并发 - Synchronized的使用与原理

2018-02-06 22:09 549 查看

Synchronized的使用

普通同步方法:锁是当前实例对象

//锁住的是当前类实例
public synchronized int getNext(){
return value++;
}


静态同步方法:锁是当前类的Class对象

//锁住的时当前Class对象
public synchronized static int getNext(){
return value++;
}


同步方法块:锁是Synchronized括号里配置的对象

//这里可以锁住任何对象。原因来自原理。
public  int getNext(){
synchronized(this){
return value++;
}
}


理解Synchronized的原理

总的来说是通过对锁对象关联的monitor的取用与释放来实现的。因此Sychroniezd也叫做内置锁。

关于monitor(理解为一个有监视作用的互斥量):http://blog.csdn.net/b9x__/article/details/79274672

java中任何一个对象都一个monitor与之关联(潜在关联),当且一个monitor被持有后,它将处于锁定状态,每一个被锁住的对象都会和一个monitor record(线程私有的数据结构)关联。Synchronized(对象)就是获取对象的monitor,synchronized下的代码就意味着放入了monitor监视区域,monitor record中中有一个Owner字段存放拥有该锁的线程的唯一标识,表示该锁被这个线程占用,这时就可以执行monitor监视区域的代码了,这些JVM在后台会自动实现。也就是Synchronized在JVM里的实现都是基于进入和退出Monitor对象来实现方法同步和代码块同步,虽然具体实现细节不一样,但是都可以通过成对的MonitorEnter和MonitorExit指令来实现。MonitorEnter指令插入在同步代码块的开始位置,当代码执行到该指令时,将会尝试获取该对象Monitor的所有权,即尝试获得该对象的锁,对象的锁存放在对象头的标志位Mark Word中(这里还有偏向锁,轻量级锁,自旋锁,Sychronized这个是重量级锁),自然monitorExit指令则插入在方法结束或异常处。

i++字节码指令:



每一个被锁住的对象和一个monitor record关联是通过对象头的MarkWord中的LockWord指向monitor record的起始地址来关联的。

任何一个对象都一个monitor与之关联,而Synchronized又是通过对锁对象关联的monitor的取用与释放来实现的,所以在同步方法块中Synchronized锁住的可以是任何对象。

抛开细节理解:每个对象都有monitor,Synchronized(对象)就是获取对象的monitor,获取到的就可以进去同步块执行(字节码指令monitorenter),执行完后释放对象的monitor(字节码指令monitorexit),这是其他线程才可获取对象的monitor。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 多线程 并发