首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >关于Java中的同步关键字(以及C#的锁)的几个问题

关于Java中的同步关键字(以及C#的锁)的几个问题
EN

Stack Overflow用户
提问于 2011-01-04 08:54:19
回答 4查看 765关注 0票数 2
  1. 在Java中是否等效于以下类?如果没有,为什么?

类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);//引发死锁?或者,如果所有这些都发生在同一个线程中,那么这是允许的吗?}

  • 在Java中是同步语句,就像C#的锁语句一样?如果不是,它们有什么区别?如果是,为什么C#也不允许锁定方法,比如Java?

  • ,所以我想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),尽管它不需要与锁直接相关的任何信息。是吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 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.EnterMonitor.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不会阻塞(除非同步)。

票数 3
EN

Stack Overflow用户

发布于 2011-01-04 09:01:40

  1. ,不,他们不一样。使用synchronized(reference){}获取给定引用(您的锁对象)上的监视器锁,在方法声明中使用synchronized使用this作为监视器锁。最终结果是,外部调用方无法获得与addsubtract方法相同的锁。
  2. 将不会出现死锁,您可以持有任意数量的监视器锁,再加上Def对象使用不同的对象进行锁定。但是即使它是第一类Abc,它也不会死锁。java中的同步锁是reetrant。因此,理论上您可以尽可能多地将它们锁在同一个线程上。
  3. 很奇怪,C#不允许在方法上使用lock,但是如果在引用中使用java synchronized关键字,它看起来也是类似的。C#的设计目标之一是足够熟悉Java开发人员,使他们能够在头脑完全被替换的情况下获得它,所以我想这并不令人惊讶。
票数 3
EN

Stack Overflow用户

发布于 2011-01-04 09:00:00

  1. --它们几乎是等价的,但有一点区别:由于Def使用内部私有对象作为锁,其他任何人都无法从外部锁定该对象。在Abc对象的情况下,其他人可能会锁定该对象,然后从另一个线程调用它的一些方法,这可能会导致死锁。这方面的实际可能性很小(因为它显然需要一些恶作剧或对另一个程序员的无知),但并不是零。因此,有些人更喜欢Def风格的安全方面,尽管AFAIK这个常见的成语是像在Def中的锁是可重入的,所以从同一个线程多次调用锁是可以的。
  2. 对不起,我不能胜任C#。在代码示例中,
  3. 是指synchronized(this)而不是synchronized(lock)吗?无论如何,由于show666不是同步的,所以对它的调用不会阻塞,即使对同步方法的另一次调用会在同一个对象上阻塞。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4591914

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档