synchronized

一 简介

在java1.5之前, java程序员在多线程开发的时候,能够用来进行并发控制的手段并不多: synchronized关键字. 虽然自1.5之后java提供了更多的并发控制方式,比如可重入锁,自旋锁等,但是synchronized关键字因为它的简单(粗暴),使用的频率还是非常高.

二 使用方式

synchronized关键字主要有两种使用方式:

1)修饰方法.这样可以使其修饰的方法称为一个线程安全的方法.

2)修饰对象.synchronized修饰对象时,可以构造一个语句块,在这个语句块里的所有语句都是线程安全的.

对于第二种情况,即当synchronized关键字修饰对象的时候,有以下两点要注意:

1)synchronized不能修饰java的8中基本数据类型:boolean,byte,char,short,int,long,float,double.否则会导致编译错误. 需要说明的是, 这8类基本数据类型的封装类是可以被synchronized关键字修饰的.

2)synchronized也不能修饰引用为null的对象.否则在运行的时候会抛出NullPointException.

当synchronized修饰基本数据类型时,发生编译错误:

当synchronized修饰引用为null的对象时,程序运行过程中会从synchronized关键字所在位置抛出NullPointException:

三 底层机制

虽然说对普通的开发者来说,只需要从功能角度和层面掌握synchronized的主要功能和基本用法,但是如果要对java理解的更加深刻的话,就得理解synchronized背后的机制了.

我自己在很长一段时间都认为,synchronized关键字在修饰方法的时候和方法内部的synchronized的同步块是没有什么差别的,我总是这样理解:

认为

class SynDemo {
	public synchronized void fun(){
		System.out.println("hello");
	}
}

class SynDemo {
	public void fun() {
		synchronized (this) {
			System.out.println("hello");
		}
	}
}

本质上是一样的.

class SynDemo {
	public synchronized static void fun() {
		System.out.println("hello");
	}
}

class SynDemo {
	public void fun() {
		synchronized (SynDemo.class) {
			System.out.println("hello");
		}
	}
}

本质上也是一样的.

虽然在功能上可以这样理解,但本质上不是.如果深入到java虚拟机指令的层次,很容易就能发现这一点.

synchronized在修饰方法的时候其实对应虚拟机指令的的方法描述符: ACC_SYNCHRONIZED, 而sysnchronized同步块对应的虚拟机指令是monitorenter和moniterexit,他们分别表示进入和退出同步区域(临界区)

四 虚拟机指令: ACC_SYNCHRONIZED

待补充

五 虚拟机指令: monitorenter和moniterexit

待补充

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>