深入了解synchronized及对象锁
1 , Synchronized锁定的是对象而非函数或代码。
2 , 每个Object只有一把锁(Lock)与之关联,当进行到Synchronized语句或函数的时候,这把锁就会被当前的线程(thread)拿走,其他的(thread)再去访问的时候拿不到锁就被暂停了
3, 只有当Synchronized的是同一个对象的才是线程安全的(thread-safe)
如:
1) public Synchronized void method1 : 锁住的是该对象,类的其中一个实例 , 当该对象(仅仅是这一个对象)在不同线程中执行这个同步方法时,线程之间会形成互斥.达到同步效果,但如果不同线程同时对该类的不同对象执行这个同步方法时,则线程之间不会形成互斥,因为他们拥有的是不同的锁.
2) Synchronized(this){//TODO } 同一
3) public Synchronizedstaticvoid method3 : 锁住的是该类,当所有该类的对象(多个对象)在不同线程中调用这个static 同步方法时,线程之间会形成互斥,达到同步效果 , 但如果多个线程同时调用method1 ,method3,则不会引互斥,具体讲看最后讲解.
4) Synchronized(Test.class){//TODo} 同三
5) synchronized(o) {} 这里面的o可以是一个任何Object对象或数组,并不一定是它本身对象或者类,谁拥有o这个锁,谁就能够操作该块程序代码.
这里面1) 与2) 是线程安全的,但1)与3) , 2)与3) 他们所拥有的锁不一样,故不是同步的,不是线程安全的.
最后, synchronized 所同步的代码应该尽量少.如果没有必要同步的就不要列为其中
联想到数据库的并发控制
假如有如下操作
1) 从数据库中读取数据
2) 修改数据
3) 提交数据
解决方案一
1) 读取数据
synchronized(XXX)
{
2)修改数据
3) 提交数据
}
解决方案二
synchronized(XXX)
{
1) 读取数据
2)修改数据
3) 提交数据
}
解决方案三
synchronized(XXX)
{
3) 提交数据
}
这里面到底用哪一种方案视具体情况而定, 要注意的是synchronized(同步)的代价,开销是很大的.