Java中的synchronized方法和synchronized块之间有什么区别?
Java中的同步方法和同步块之间有什么区别?
我一直在网上寻找答案,人们似乎对这个问题很不确定:-(
我认为两者之间没有区别,只是同步块可能在范围上更加局部化,因此locking时间较短。
而且在locking一个静态方法的情况下,locking是什么? 什么是locking类的含义?
同步的方法使用方法接收器作为锁(即非静态方法,封闭类静态方法)。 Synchronized
块使用expression式作为锁。
所以以下两种方法相当于locking前景:
synchronized void mymethod() { ... } void mymethod() { synchronized (this) { ... } }
对于静态方法,该类将被locking:
class MyClass { synchronized static mystatic() { ... } static mystaticeq() { syncrhonized (MyClass.class) { ... } } }
对于同步块,可以使用任何非null
对象作为锁:
synchronized (mymap) { mymap.put(..., ...); }
locking范围
对于同步方法,锁将在整个方法范围内保留,而在synchronized
块中,锁仅在该块范围内保持(否则称为临界区)。 在实践中,如果能够certificateJVM可以安全地完成,则允许通过从synchronized
块执行中去除一些操作来优化JVM。
同步方法是简写。 这个:
class Something { public synchronized void doSomething() { ... } public static synchronized void doSomethingStatic() { ... } }
对于所有意图和目的而言,都等同于:
class Something { public void doSomething() { synchronized(this) { ... } } public static void doSomethingStatic() { synchronized(Something.class) { ... } } }
(其中Something.class
是类Something.class
的类对象。)
所以确实,通过一个同步块,你可以更具体地了解你的锁,并且当你想要使用它时更加细化,但除此之外没有什么区别。
是的,这是一个区别。 另一个是,你可以获得比this
其他对象的锁。
关键的区别是:如果你声明一个方法被同步,那么方法的整个主体就会被同步; 但是,如果使用同步块,则可以只包围同步块中方法的“关键部分”,而将方法的其余部分留在块之外。
如果整个方法是关键部分的一部分,那么实际上没有区别。 如果情况并非如此,那么你应该在临界区域周围使用同步块。 同步块中的语句越多,获得的总体并行性就越低,所以您希望将这些语句保持在最低水平。
同步的方法locking方法所在的对象实例。
作为一个同步块可以locking任何对象 – 通常是一个互斥对象定义为一个实例variables。 这允许更多的控制什么锁操作。
我认为两者之间没有区别,只是同步块可能在范围上更加局部化,因此locking时间较短。
是。 你是对的。 与synchronized
方法不同,synchronized语句必须指定提供内部锁的对象。
来自java教程的例子:
public void addName(String name) { synchronized(this) { lastName = name; nameCount++; } nameList.add(name); }
同步语句对于通过细粒度同步来提高并发性也很有用。 你可以在下面的用例的相同教程页面find很好的例子。
假设,例如,类MsLunch
有两个实例字段c1和c2,它们从不一起使用。 这些字段的所有更新都必须synchronized
,但没有理由阻止更新c1与更新c2进行交错,并且通过创build不必要的阻塞来降低并发性。 而不是使用同步的方法或使用与此相关的锁,我们创build两个对象来提供锁 。
而且在locking一个静态方法的情况下,locking是什么? 什么是locking类的含义?
在这种情况下,线程获取与该类关联的Class对象的内部锁。 因此,对类的静态字段的访问是由与该类的任何实例的锁截然不同的锁来控制的。
当你使一个方法同步 (非static
)时:
同一对象上的两个synchronized
方法的调用不可能交错。 当一个线程正在执行一个对象的同步方法时,所有其他调用同一对象的同步方法的线程将阻塞(挂起执行),直到第一个线程完成对象。
如果你使一个方法static synchronized
:
对同一类的不同对象的两个static synchronized
方法的调用是不可能交错的。 当一个线程正在为A类的一个对象执行一个static synchronized
方法时,所有其他的线程在A类块的任何对象上调用static synchronized
方法(暂停执行),直到第一个线程完成方法执行。
你可以在这个SE问题中find更好的同步方法:
避免在Java中同步(this)?