我有一些关于同步关键字的用法和意义的问题。

synchronized关键字有什么意义? 什么时候应该同步方法? 它在程序上和逻辑上意味着什么?


当前回答

synchronized关键字是什么?

线程主要通过共享对字段和引用字段所引用的对象的访问进行通信。这种通信形式非常高效,但可能会产生两种错误:线程干扰和内存一致性错误。防止这些错误所需的工具是同步。

同步块或方法可以防止线程干扰,并确保数据是一致的。在任何时候,只有一个线程可以通过获得锁来访问同步块或方法(临界区)。其他线程将等待锁释放来访问临界区。

方法何时同步?

将synchronized添加到方法定义或声明时,方法是同步的。您还可以在方法中同步特定的代码块。

它在语法上和逻辑上意味着什么?

这意味着只有一个线程可以通过获得锁来访问临界区。除非这个线程释放这个锁,否则所有其他线程将不得不等待获得一个锁。他们不能在没有锁的情况下进入临界区。

这不是魔法能办到的。程序员的职责是识别应用程序中的关键部分并相应地保护它。Java提供了一个框架来保护你的应用程序,但是在哪里以及保护哪些部分是程序员的责任。

更多细节,请参阅java文档页

内在锁和同步:

同步是围绕一个称为内在锁或监视器锁的内部实体构建的。内在锁在同步的两个方面都发挥作用:强制对对象状态的独占访问,并建立对可见性至关重要的happens-before关系。

每个对象都有一个与之相关的内在锁。按照惯例,需要独占和一致访问对象字段的线程必须在访问对象字段之前获得对象的内在锁,然后在使用完对象字段时释放内在锁。

线程在获得锁和释放锁之间拥有内在锁。只要一个线程拥有一个内在锁,其他线程就不能获得相同的锁。另一个线程在试图获取锁时将阻塞。

当线程释放一个内在锁时,在该操作和后续获得的任何相同锁之间建立happens-before关系。

使方法同步有两个效果:

首先,对同一对象的同步方法的两次调用不可能交织。

当一个线程正在为一个对象执行同步方法时,所有为同一对象调用同步方法的其他线程将暂停执行,直到第一个线程处理完该对象。

其次,当同步方法退出时,它自动与同一对象的同步方法的任何后续调用建立happens-before关系。

这保证了对对象状态的更改对于所有线程都是可见的。

寻找同步的其他替代方案:

避免在Java中同步(这)?

其他回答

Synchronized simple意味着没有两个线程可以同时访问块/方法。当我们说一个类的任何块/方法都是同步的,这意味着一次只有一个线程可以访问它们。在内部,试图访问它的线程首先在该对象上获得一个锁,只要这个锁不可用,其他线程就不能访问该类实例的任何同步方法/块。

注意,另一个线程可以访问同一对象的方法,该方法没有被定义为同步。线程可以通过调用来释放锁

Object.wait()

synchronized关键字使线程在输入方法时获得锁,以便同一时间只有一个线程可以执行该方法(对于给定的对象实例,除非它是静态方法)。

这通常被称为使类线程安全,但我认为这是一种委婉说法。虽然同步确实可以保护Vector的内部状态不被破坏,但这通常对Vector的用户没有太大帮助。

考虑一下:

 if (vector.isEmpty()){
     vector.add(data);
 }

尽管所涉及的方法是同步的,但由于它们分别被锁定和解锁,两个不幸计时的线程可以创建具有两个元素的向量。

所以实际上,你也必须在你的应用程序代码中同步。

因为方法级同步是a)当你不需要它的时候很昂贵,b)当你需要同步的时候不够用,所以现在有了不同步的替换(Vector的情况下是ArrayList)。

最近,并发包已经发布,其中包含许多处理多线程问题的聪明实用程序。

synchronized是Java中的关键字,用于在多线程环境中使发生在关系之前,以避免内存不一致和线程干扰错误。

synchronized关键字可以防止多个线程并发访问一个代码块或对象。Hashtable的所有方法都是同步的,因此一次只有一个线程可以执行其中的任何方法。

当使用非同步结构(如HashMap)时,必须在代码中构建线程安全特性以防止一致性错误。

下面是来自Java教程的解释。

考虑下面的代码:

public class SynchronizedCounter { private int c = 0; public synchronized void increment() { c++; } public synchronized void decrement() { c--; } public synchronized int value() { return c; } } if count is an instance of SynchronizedCounter, then making these methods synchronized has two effects: First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object. Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.