类Abc {私有int c= 0;公共同步空添加( int a) {c += a;}公共同步空减(Int a) {c -= a;}类Def {私有int c= 0;私有最终对象锁=新对象();公共空添加(Int a) {同步(锁){c += a;}公共空减(Int a) {同步(锁){c -= a;}}
Def中,使用this作为同步参数而不是lock会有什么问题?以下是问题所在吗?Def def =新的Def()同步(def) { def.add(5);//引发死锁?或者,如果所有这些都发生在同一个线程中,那么这是允许的吗?}
synchronized (this)的问题可以用下面的例子来描述?类Xyz {私有int c;公共空添加(Int a) {同步(此){c += a;}公共空减(Int a) { -= a;}公共空show666() {返回666;}}
Thread1调用xyz.add(0),同时Thread2尝试调用xyz.show666()。Thread2不得不等待Thread1完成xyz.add(0),尽管它不需要与锁直接相关的任何信息。是吗?
发布于 2011-01-04 09:40:02
在
1中,以下类是等价的吗?如果没有,为什么?
它们因它们在哪个实例上同步而不同,因此受到这些实例之间的差异的影响。
类Abc使用正在调用该方法的Abc实例。访问实例的其他代码也可以通过在同步块中显式使用实例来进行同步。
类Def中的同步代码块显式地命名与它们同步的实例。由于这个实例对Def实例是私有的,所以Def外部的代码不能使用它进行同步(除非实例被泄露)。
有些人可能会认为Def方法要安全得多,因为您应该使用私有实例变量,因此封装锁是很重要的。
最后,同步关键字与使用同步语句之间有区别,例如,同步语句可以锁定任何对象,而不仅仅是执行代码的实例,同步关键字的效率略高,等等。
同样,在Def中使用这个作为同步参数而不是锁的问题是什么?
没问题。在实例方法上使用同步关键字在语义上与在this上同步块中包装方法的代码相同(同步关键字稍微高效一些)。在静态方法上使用同步关键字与在类本身上使用同步块(例如synchronized(FooBar.class) { ... })是一样的。
2b是以下问题吗?
不,Java中的锁是可重入的,这意味着在保护实例上持有锁的线程可以进入和退出在同一个实例上同步的任何其他代码块。
Java3a是
中的同步语句,就像C#的锁语句一样?如果不是,它们有什么区别?
语义上等价的。
http://en.csharp-online.net/CSharp_FAQ:_What_is_the_difference_between_CSharp_lock_and_Java_synchronized#Synchronized_code_blocks
但是请注意这个关于Monitor.Enter和Monitor.Exit的答案
Are there any differences between Java's "synchronized" and C#'s "lock"?
如果
3b是的话,为什么C#也不允许像C#允许的那样锁定这些方法呢?
确实如此--使用[MethodImpl(MethodImplOptions.Synchronized)]注释。
http://en.csharp-online.net/CSharp_FAQ:_What_is_the_difference_between_CSharp_lock_and_Java_synchronized#Synchronized_methods
4 Thread1调用xyz.add(0),同时Thread2尝试调用xyz.show666()。Thread2不得不等待Thread1完成xyz.add(0),尽管它不需要任何与锁直接相关的信息。是这样吗?
不,很多人认为“锁定”一个实例会影响整个实例。它只影响在该实例上同步的同步代码(同步方法和同步语句中的代码)。不同步代码不受影响(至少在到达同步语句或调用同步方法之前)。
不同步方法show666()不会导致线程阻塞。如果将synchronized(this)语句更改为synchronized方法,则不会发生任何变化--同样,show666不会阻塞(除非同步)。
https://stackoverflow.com/questions/4591914
复制相似问题