Java多线程Synchronized心得
2011-07-06 13:58
441 查看
转载:http://www.vanjor.org/blog/2011/04/java-synchronized/
两年前,在编写一个多线程采集器的时候,写了一篇心得《Java多线程Synchronized的注意细节》,但是随后的使用中,发现仍然没有完全分清场景与背后原理。现在随着实际应用,终于也有所新的成熟的理解了。
Synchronized是java语言级别内置的同步机制,不同与java中的Semaphore,Mutex。Synchronized的背后机制是Java在语言级上的锁机制:
类锁:对于每一个类,自动配套一个类锁,该锁临界量为1
实例锁:对于每一个类实例化后的一个对象,自动配套一个对象锁,该锁临界量为1
对于类锁,目前注意到,只能应用到类得某个方法上:
静态方法锁:static synchronized method();
对于实例锁,有以下几种方式:
非静态方法锁:synchronized method();
代码块锁:synchronized{ }或synchronized(this){ }
指定类实例锁:synchronized(Object ob){ }
非静态方法锁与代码块锁实质都一样,是对当前所属类得实例加锁。而指定类实例锁,是对括号里的对象ob加锁,这一点很有意思,灵活运用指定类锁可以构建一些稍微负责的并行程序模型。
其中类锁与实例锁各自独立,不相互冲突,一个synchronized 指定锁,要么是类锁,要么是实例锁,是互斥的。
在多线程中,依然是引用日本作者结成浩的《java多线程设计模式》中的例子:
问题:
那么,对于Something类的两个实例a与b,那么下列组方法何以被1个以上线程同时访问呢
x.isSyncA()与x.isSyncB()
x.isSyncA()与y.isSyncA()
x.cSyncA()与y.cSyncB()
x.isSyncA()与Something.cSyncA()
答案:
都是对同一个实例的synchronized域访问,因此不能被同时访问
是针对不同实例的,因此可以同时被访问
因为是static synchronized,所以不同实例之间仍然会被限制,相当于Something.isSyncA()与 Something.isSyncB()了,因此不能被同时访问。
能够同时访问,因为一个是实例锁,一个是类锁。
synchronized的语言级别锁机制,让并发项目时,无需增加锁控制类,直接本身原生态支持,十分方便,但注意到,synchronized锁只有两个粒度,一个是类锁,一个是实例锁,而且临界区互斥量为1,对于有些需要临界区大于1的,锁粒度更大,动态调控,那synchronized就不够用了。得需要专门的信号量等机制了。
最后一点是synchronized关键词不能被直接继承,子类在继承负责,覆盖父类的synchronized方法时候,必须同样显示用synchronized关键词。而子类如果不覆盖父类synchronized关键词的非静态方法,直接继承并使用父类的非静态方法时,父类的synchronized字段在子类对象仍然是有效的。
两年前,在编写一个多线程采集器的时候,写了一篇心得《Java多线程Synchronized的注意细节》,但是随后的使用中,发现仍然没有完全分清场景与背后原理。现在随着实际应用,终于也有所新的成熟的理解了。
Synchronized是java语言级别内置的同步机制,不同与java中的Semaphore,Mutex。Synchronized的背后机制是Java在语言级上的锁机制:
类锁:对于每一个类,自动配套一个类锁,该锁临界量为1
实例锁:对于每一个类实例化后的一个对象,自动配套一个对象锁,该锁临界量为1
对于类锁,目前注意到,只能应用到类得某个方法上:
静态方法锁:static synchronized method();
对于实例锁,有以下几种方式:
非静态方法锁:synchronized method();
代码块锁:synchronized{ }或synchronized(this){ }
指定类实例锁:synchronized(Object ob){ }
非静态方法锁与代码块锁实质都一样,是对当前所属类得实例加锁。而指定类实例锁,是对括号里的对象ob加锁,这一点很有意思,灵活运用指定类锁可以构建一些稍微负责的并行程序模型。
其中类锁与实例锁各自独立,不相互冲突,一个synchronized 指定锁,要么是类锁,要么是实例锁,是互斥的。
在多线程中,依然是引用日本作者结成浩的《java多线程设计模式》中的例子:
问题:
public class Something(){ public synchronized void isSyncA(){} public synchronized void isSyncB(){} public static synchronized void cSyncA(){} public static synchronized void cSyncB(){} }
那么,对于Something类的两个实例a与b,那么下列组方法何以被1个以上线程同时访问呢
x.isSyncA()与x.isSyncB()
x.isSyncA()与y.isSyncA()
x.cSyncA()与y.cSyncB()
x.isSyncA()与Something.cSyncA()
答案:
都是对同一个实例的synchronized域访问,因此不能被同时访问
是针对不同实例的,因此可以同时被访问
因为是static synchronized,所以不同实例之间仍然会被限制,相当于Something.isSyncA()与 Something.isSyncB()了,因此不能被同时访问。
能够同时访问,因为一个是实例锁,一个是类锁。
synchronized的语言级别锁机制,让并发项目时,无需增加锁控制类,直接本身原生态支持,十分方便,但注意到,synchronized锁只有两个粒度,一个是类锁,一个是实例锁,而且临界区互斥量为1,对于有些需要临界区大于1的,锁粒度更大,动态调控,那synchronized就不够用了。得需要专门的信号量等机制了。
最后一点是synchronized关键词不能被直接继承,子类在继承负责,覆盖父类的synchronized方法时候,必须同样显示用synchronized关键词。而子类如果不覆盖父类synchronized关键词的非静态方法,直接继承并使用父类的非静态方法时,父类的synchronized字段在子类对象仍然是有效的。
相关文章推荐
- Java多线程Synchronized心得
- Java学习--多线程中synchronized的使用心得
- (转)初学Java多线程:使用Synchronized关键字同步类方法
- java多线程设计wait、notify、notifyall、synchronized的使用机制
- java 多线程 Synchronized方法和方法块 synchronized(this)和synchronized(object)的理解
- JAVA多线程之Synchronized关键字
- 关于java关键字synchronized的一些心得体会
- Java多线程之~~~synchronized添加参数来实现独立的代码片段
- Java基础(高级)——多线程的理解和Synchronized实例,以及线程间通信,wait,notify等方法
- Java多线程:线程同步与关键字synchronized
- java多线程——同步块synchronized详解
- java多线程 21 : ReentrantReadWriteLock ,synchronized和ReentrantLock的对比
- Java多线程synchronized、ReentrantLock、ReentrantReadWriteLock 和StampedLock 的对比
- Java多线程Synchronized的注意细节
- Java 多线程:synchronized 关键字 3ff0 用法(修饰类,方法,静态方法,代码块)
- Java之多线程内存可见性_2(synchronized实现可见性代码)
- 多线程拨号Java版(探讨synchronized和Lock线程同步)
- Java多线程之synchronized的使用技巧
- java多线程编程核心技术2-Synchronized
- Java多线程:synchronized