synchronized与static synchronized 的区别以及synchronized继承问题
来源:互联网 发布:c语言 延时 linux 编辑:程序博客网 时间:2024/05/18 06:23
1.synchronized与static synchronized 的区别
synchronized是对类的当前实例进行加锁,防止其他线程同时访问该类的该实例的所有synchronized块,注意这里是“类的当前实例”, 类的两个不同实例就没有这种约束了。那么static synchronized恰好就是要控制类的所有实例的访问了,static synchronized是限制线程同时访问jvm中该类的所有实例同时访问对应的代码快。实际上,在类中某方法或某代码块中有 synchronized,那么在生成一个该类实例后,改类也就有一个监视快,放置线程并发访问改实例synchronized保护快,而static synchronized则是所有该类的实例公用一个监视快了,也也就是两个的区别了,也就是synchronized相当于 this.synchronized,而
static synchronized相当于Something.synchronized.
一个日本作者-结成浩的《java多线程设计模式》有这样的一个列子:
pulbic class Something(){
public synchronized void isSyncA(){}
public synchronized void isSyncB(){}
public static synchronized void cSyncA(){}
public static synchronized void cSyncB(){}
}
那么,加入有Something类的两个实例a与b,那么下列组方法何以被1个以上线程同时访问呢
a. x.isSyncA()与x.isSyncB()
b. x.isSyncA()与y.isSyncA()
c. x.cSyncA()与y.cSyncB()
d. x.isSyncA()与Something.cSyncA()
这里,很清楚的可以判断:
a,都是对同一个实例的synchronized域访问,因此不能被同时访问
b,是针对不同实例的,因此可以同时被访问
c,因为是static synchronized,所以不同实例之间仍然会被限制,相当于Something.isSyncA()与 Something.isSyncB()了,因此不能被同时访问。
那么,第d呢?,书上的 答案是可以被同时访问的,答案理由是synchronzied的是实例方法与synchronzied的类方法由于锁定(lock)不同的原因。
个人分析也就是synchronized 与static synchronized 相当于两帮派,各自管各自,相互之间就无约束了,可以被同时访问。目前还不是分清楚java内部设计synchronzied是怎么样实现的。
结论:A: synchronized static是某个类的范围,synchronized static cSync{}防止多个线程同时访问这个 类中的synchronized static 方法。它可以对类的所有对象实例起作用。
B: synchronized 是某实例的范围,synchronized isSync(){}防止多个线程同时访问这个实例中的synchronized 方法。
2.synchronized方法与synchronized代码快的区别
synchronized methods(){} 与synchronized(this){}之间没有什么区别,只是 synchronized methods(){} 便于阅读理解,而synchronized(this){}可以更精确的控制冲突限制访问区域,有时候表现更高效率。
3.synchronized关键字是不能继承的
我想这一点也是很值得注意的,继承时子类的覆盖方法必须显示定义成synchronized
网上看到很多对关键字synchronized继承性的描述只有一句"关键字synchronized不能被继承",并没有描述具体场景,于是自己做了以下测试。
//父类
public class Super {
static Logger logger = Logger.getLogger(Super.class);
// 同步方法 @SuppressWarnings("static-access") public synchronized void testMothed() { try { Thread.currentThread().sleep(5000);//休眠5秒。 } catch (InterruptedException e) { e.printStackTrace(); } logger.info(Thread.currentThread().getName() +","+ this); }
}
//子类1
public class Sub1 extends Super {
// 不重写父类的同步方法 }
//子类2
public class Sub2 extends Super {
// 重写父类的同步方法,但不加synchronized。
@SuppressWarnings("static-access")
public void testMothed() {
try {
Thread.currentThread().sleep(3000);//为区别与父类中休眠时间,改为3秒。 }
catch (InterruptedException e) {
e.printStackTrace(); }
logger.info(Thread.currentThread().getName() +","+ this); }
}
//测试类
public class SynchronizedTest {
static Logger logger = Logger.getLogger(SynchronizedTest.class);
public static void main(String[] args) throws Exception {
// 子类对象1 final Sub1 sub1 = new Sub1();
final int count = 5; // 创建count个不同线程,调用子类对象1同一方法
for (int i = 0; i < count; i++) {
new Thread() {
public void run() {
sub1.testMothed(); }
}.start(); }
// 让上面所有子线程有足够时间执行结束 TimeUnit.SECONDS.sleep((count+1)*5);
logger.info("===============================================");
// 子类对象2
final Sub2 sub2 = new Sub2(); // 创建count个不同线程,调用子类对象2同一方法
for (int i = 0; i < count; i++) {
new Thread() {
public void run() {
sub2.testMothed(); } }.start(); } } }
执行结果:
2013-12-03 12:40:18,043 [INFO]----> Thread-0,java_lang.thread_synchronized.Sub1@86f241 2013-12-03 12:40:23,044 [INFO]----> Thread-4,java_lang.thread_synchronized.Sub1@86f241 2013-12-03 12:40:28,044 [INFO]----> Thread-3,java_lang.thread_synchronized.Sub1@86f241 2013-12-03 12:40:33,044 [INFO]----> Thread-2,java_lang.thread_synchronized.Sub1@86f241 2013-12-03 12:40:38,045 [INFO]----> Thread-1,java_lang.thread_synchronized.Sub1@86f241 2013-12-03 12:40:43,044 [INFO]----> =============================================== 2013-12-03 12:40:46,045 [INFO]----> Thread-6,java_lang.thread_synchronized.Sub2@15dfd77 2013-12-03 12:40:46,045 [INFO]----> Thread-7,java_lang.thread_synchronized.Sub2@15dfd77 2013-12-03 12:40:46,045 [INFO]----> Thread-5,java_lang.thread_synchronized.Sub2@15dfd77 2013-12-03 12:40:46,046 [INFO]----> Thread-8,java_lang.thread_synchronized.Sub2@15dfd77 2013-12-03 12:40:46,046 [INFO]----> Thread-9,java_lang.thread_synchronized.Sub2@15dfd77
从上面可以看出,
不同线程对子类Sub1的同一对象sub1,调用testMothed,有同步效果,分别进入该方法,分别等待5秒。(红色与红色时间差)
不同线程对子类Sub2的同一对象sub2,调用testMothed,没有同步效果,所有线程同时进入该方法并同时等待3秒(蓝色到绿色时间差),然后同时执行(绿色时间一样)。
因此,对"关键字synchronized不能被继承",完整描述应该是:
1、子类继承父类时,如果没有重写父类中的同步方法,子类同一对象,在不同线程并发调用该方法时,具有同步效果。
2、子类继承父类,并且重写父类中的同步方法,但没有添加关键字synchronized,子类同一对象,在不同线程并发调用该方法时,不再具有同步效果,这种情形即是"关键字synchronized不能被继承"的转述。(貌似很多人在这一点上存在疑惑)。
转:
http://www.cnblogs.com/shipengzhi/articles/2223100.html
- synchronized与static synchronized 的区别以及synchronized继承问题
- synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- Java synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- synchronized与static synchronized 的区别
- myeclipse2017ci5正确破解的方法
- 欢迎使用CSDN-markdown编辑器
- Http和Socket连接区别
- Samba和FTP服务器以及NFS网络文件服务和SSH
- oracle数学(字)函数
- synchronized与static synchronized 的区别以及synchronized继承问题
- Oil Deposits
- Object.create的用法
- MTK_FAQ_Conectivity
- 计算机网络原理知识点(第一章:概述)
- Ray Tracing 的c++简单实现
- 福州大学第十三届程序设计竞赛题解【8/9】
- 深度增强学习(DRL)漫谈
- 声明