Java “同步”是什么意思?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1085709/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:25:39  来源:igfitidea点击:

What does 'synchronized' mean?

javamultithreadingkeywordsynchronized

提问by Johanna

I have some questions regarding the usage and significance of the synchronizedkeyword.

我对synchronized关键字的用法和重要性有一些疑问。

  • What is the significance of the synchronizedkeyword?
  • When should methods be synchronized?
  • What does it mean programmatically and logically?
  • synchronized关键字的意义是什么?
  • 什么时候应该使用方法synchronized
  • 它在编程和逻辑上意味着什么?

采纳答案by Stu Thompson

The synchronizedkeyword is all about different threads reading and writing to the same variables, objects and resources. This is not a trivial topic in Java, but here is a quote from Sun:

synchronized关键字是关于不同线程对相同变量、对象和资源的读取和写入。这在 Java 中不是一个微不足道的话题,但这里引用了 Sun 的话:

synchronizedmethods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object's variables are done through synchronized methods.

synchronized方法启用了一种防止线程干扰和内存一致性错误的简单策略:如果一个对象对多个线程可见,则对该对象变量的所有读取或写入都通过同步方法完成。

In a very, very small nutshell:When you have two threads that are reading and writing to the same 'resource', say a variable named foo, you need to ensure that these threads access the variable in an atomic way. Without the synchronizedkeyword, your thread 1 may not see the change thread 2 made to foo, or worse, it may only be half changed. This would not be what you logically expect.

简而言之:当您有两个线程正在读取和写入同一个“资源”时,比如说一个名为 的变量foo,您需要确保这些线程以原子方式访问该变量。如果没有synchronized关键字,您的线程 1 可能看不到线程 2 对 所做的更改foo,或者更糟的是,它可能只更改了一半。这不会是您逻辑上所期望的。

Again, this is a non-trivial topic in Java. To learn more, explore topics here on SO and the Interwebs about:

同样,这在 Java 中是一个重要的话题。要了解更多信息,请在 SO 和 Internet 上探索有关以下内容的主题:

Keep exploring these topics until the name "Brian Goetz"becomes permanently associated with the term "concurrency"in your brain.

继续探索这些主题,直到“Brian Goetz”这个名字在你的大脑中与术语“并发”永久关联。

回答by Spence

To my understanding synchronized basically means that the compiler write a monitor.enter and monitor.exit around your method. As such it may be thread safe depending on how it is used (what I mean is you can write an object with synchronized methods that isn't threadsafe depending on what your class does).

根据我的理解,同步基本上意味着编译器围绕您的方法编写一个 monitor.enter 和 monitor.exit。因此,它可能是线程安全的,具体取决于它的使用方式(我的意思是,您可以使用同步方法编写一个对象,而这些方法不是线程安全的,具体取决于您的类的功能)。

回答by Thilo

The synchronizedkeyword causes a thread to obtain a lock when entering the method, so that only one thread can execute the method at the same time (for the given object instance, unless it is a static method).

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

This is frequently called making the class thread-safe, but I would say this is a euphemism. While it is true that synchronization protects the internal state of the Vector from getting corrupted, this does not usually help the user of Vector much.

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

Consider this:

考虑一下:

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

Even though the methods involved are synchronized, because they are being locked and unlocked individually, two unfortunately timed threads can create a vector with two elements.

即使所涉及的方法是同步的,因为它们是单独锁定和解锁的,不幸的是,两个定时线程可以创建一个包含两个元素的向量。

So in effect, you have to synchronize in your application code as well.

因此,实际上,您还必须在应用程序代码中进行同步。

Because method-level synchronization is a) expensive when you don't need it and b) insufficient when you need synchronization, there are now un-synchronized replacements (ArrayList in the case of Vector).

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

More recently, the concurrency package has been released, with a number of clever utilities that take care of multi-threading issues.

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

回答by paul

Think of it as a kind of turnstile like you might find at a football ground. There are parallel steams of people wanting to get in but at the turnstile they are 'synchronised'. Only one person at a time can get through. All those wanting to get through will do, but they may have to wait until they can go through.

把它想象成一种旋转门,就像你在足球场上看到的那样。有很多人想要进入,但在旋转门他们是“同步”的。一次只能有一个人通过。所有想通过的人都可以,但他们可能必须等到他们能够通过。

回答by Codemwnci

synchronizedmeans that in a multi threaded environment, an object having synchronizedmethod(s)/block(s) does not let two threads to access the synchronizedmethod(s)/block(s) of code at the same time. This means that one thread can't read while another thread updates it.

synchronized意味着在多线程环境中,具有synchronized方法/块的对象 不会让两个线程同时访问代码的synchronized方法/块。这意味着一个线程无法读取而另一个线程更新它。

The second thread will instead wait until the first thread completes its execution. The overhead is speed, but the advantage is guaranteed consistency of data.

第二个线程将改为等待,直到第一个线程完成其执行。开销是速度,但优势是保证数据的一致性。

If your application is single threaded though, synchronizedblocks does not provide benefits.

但是,如果您的应用程序是单线程的,则synchronized块不会提供任何好处。

回答by jmort253

The synchronizedkeyword prevents concurrent access to a block of code or object by multiple threads. All the methods of Hashtableare synchronized, so only one thread can execute any of them at a time.

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

When using non-synchronizedconstructs like HashMap, you must build thread-safety features in your code to prevent consistency errors.

使用非synchronized结构时,如HashMap,您必须在代码中构建线程安全功能以防止一致性错误。

回答by Aniket Thakur

synchronized simple means no two threads can access the block/method simultaneously. When we say any block/method of a class is synchronized it means only one thread can access them at a time. Internally the thread which tries to access it first take a lock on that object and as long as this lock is not available no other thread can access any of the synchronized methods/blocks of that instance of the class.

同步简单意味着没有两个线程可以同时访问块/方法。当我们说一个类的任何块/方法是同步的时,这意味着一次只有一个线程可以访问它们。在内部,尝试访问它的线程首先对该对象进行锁定,只要此锁定不可用,其他线程就无法访问该类实例的任何同步方法/块。

Note another thread can access a method of the same object which is not defined to be synchronized. A thread can release the lock by calling

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

Object.wait()

回答by Dheeraj Sachan

Well, I think we had enough of theoretical explanations, so consider this code

好吧,我认为我们有足够的理论解释,所以考虑一下这段代码

public class SOP {
    public static void print(String s) {
        System.out.println(s+"\n");
    }
}

public class TestThread extends Thread {
    String name;
    TheDemo theDemo;
    public TestThread(String name,TheDemo theDemo) {
        this.theDemo = theDemo;
        this.name = name;
        start();
    }
    @Override
    public void run() {
        theDemo.test(name);
    }
}

public class TheDemo {
    public synchronized void test(String name) {
        for(int i=0;i<10;i++) {
            SOP.print(name + " :: "+i);
            try{
                Thread.sleep(500);
            } catch (Exception e) {
                SOP.print(e.getMessage());
            }
        }
    }
    public static void main(String[] args) {
        TheDemo theDemo = new TheDemo();
        new TestThread("THREAD 1",theDemo);
        new TestThread("THREAD 2",theDemo);
        new TestThread("THREAD 3",theDemo);
    }
}

Note: synchronizedblocks the next thread's call to method test() as long as the previous thread's execution is not finished. Threads can access this method one at a time. Without synchronizedall threads can access this method simultaneously.

注意:synchronized只要前一个线程的执行没有完成,就会阻塞下一个线程对 test() 方法的调用。线程可以一次访问一个方法。无需synchronized所有线程都可以同时访问此方法。

When a thread calls the synchronized method 'test' of the object (here object is an instance of 'TheDemo' class) it acquires the lock of that object, any new thread cannot call ANY synchronized method of the same object as long as previous thread which had acquired the lock does not release the lock.

当一个线程调用对象的同步方法'test'时(这里的对象是'TheDemo'类的一个实例)它获取了该对象的锁,任何新线程都不能调用同一个对象的任何同步方法,只要前一个线程获得了锁的不会释放锁。

Similar thing happens when any static synchronized method of the class is called. The thread acquires the lock associated with the class(in this case any non static synchronized method of an instance of that class can be called by any thread because that object level lock is still available). Any other thread will not be able to call any static synchronized method of the class as long as the class level lock is not released by the thread which currently holds the lock.

当调用类的任何静态同步方法时,会发生类似的事情。线程获取与类关联的锁(在这种情况下,任何线程都可以调用该类实例的任何非静态同步方法,因为该对象级锁仍然可用)。只要当前持有锁的线程没有释放类级锁,任何其他线程将无法调用该类的任何静态同步方法。

Output with synchronised

同步输出

THREAD 1 :: 0
THREAD 1 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 1 :: 4
THREAD 1 :: 5
THREAD 1 :: 6
THREAD 1 :: 7
THREAD 1 :: 8
THREAD 1 :: 9
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 3 :: 4
THREAD 3 :: 5
THREAD 3 :: 6
THREAD 3 :: 7
THREAD 3 :: 8
THREAD 3 :: 9
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 2 :: 4
THREAD 2 :: 5
THREAD 2 :: 6
THREAD 2 :: 7
THREAD 2 :: 8
THREAD 2 :: 9

Output without synchronized

输出不同步

THREAD 1 :: 0
THREAD 2 :: 0
THREAD 3 :: 0
THREAD 1 :: 1
THREAD 2 :: 1
THREAD 3 :: 1
THREAD 1 :: 2
THREAD 2 :: 2
THREAD 3 :: 2
THREAD 1 :: 3
THREAD 2 :: 3
THREAD 3 :: 3
THREAD 1 :: 4
THREAD 2 :: 4
THREAD 3 :: 4
THREAD 1 :: 5
THREAD 2 :: 5
THREAD 3 :: 5
THREAD 1 :: 6
THREAD 2 :: 6
THREAD 3 :: 6
THREAD 1 :: 7
THREAD 2 :: 7
THREAD 3 :: 7
THREAD 1 :: 8
THREAD 2 :: 8
THREAD 3 :: 8
THREAD 1 :: 9
THREAD 2 :: 9
THREAD 3 :: 9

回答by Sharad

synchronized is a keyword in Java which is used to make happens before relationship in multithreading environment to avoid memory inconsistency and thread interference error.

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

回答by Gima

Overview

概述

Synchronized keyword in Java has to do with thread-safety, that is, when multiple threads read or write the same variable.
This can happen directly (by accessing the same variable) or indirectly (by using a class that uses another class that accesses the same variable).

Java 中的 Synchronized 关键字与线程安全有关,即当多个线程读取或写入同一个变量时。
这可以直接(通过访问同一变量)或间接(通过使用使用另一个访问同一变量的类的类)发生。

The synchronized keyword is used to define a block of code where multiple threads can access the same variable in a safe way.

synchronized 关键字用于定义一个代码块,其中多个线程可以安全地访问同一个变量。

Deeper

更深层次的

Syntax-wise the synchronizedkeyword takes an Objectas it's parameter (called a lock object), which is then followed by a { block of code }.

从语法上看,synchronized关键字将 anObject作为参数(称为lock object),然后后跟 a { block of code }

  • When execution encounters this keyword, the current thread tries to "lock/acquire/own" (take your pick) the lock objectand execute the associated block of code after the lock has been acquired.

  • Any writes to variables inside the synchronized code block are guaranteed to be visible to every other thread that similarly executes code inside a synchronized code block using the same lock object.

  • Only one thread at a time can hold the lock, during which time all other threads trying to acquire the same lock objectwill wait (pause their execution). The lock will be released when execution exits the synchronized code block.

  • 当执行遇到此关键字时,当前线程会尝试“锁定/获取/拥有”(选择)锁定对象并在获取锁定后执行关联的代码块。

  • 任何对同步代码块内变量的写入都保证对使用相同锁对象在同步代码块内类似地执行代码的每个其他线程可见。

  • 一次只有一个线程可以持有锁,在此期间所有其他试图获取同一个锁对象的线程将等待(暂停它们的执行)。当执行退出同步代码块时,锁将被释放。

Synchronized methods:

同步方法:

Adding synchronizedkeyword to a method definition is equal to the entire method body being wrapped in a synchronized code block with the lock objectbeing this(for instance methods)and ClassInQuestion.getClass()(for class methods).

synchronized方法定义添加关键字等于将整个方法体包装在同步代码块中,锁定对象this(对于实例方法)ClassInQuestion.getClass()(对于类方法)

- Instance method is a method which does not have statickeyword.
- Class method is a method which has statickeyword.

- 实例方法是一种没有static关键字的方法。
- 类方法是具有static关键字的方法。

Technical

技术的

Without synchronization, it is not guaranteed in which order the reads and writes happen, possibly leaving the variable with garbage.
(For example a variable could end up with half of the bits written by one thread and half of the bits written by another thread, leaving the variable in a state that neither of the threads tried to write, but a combined mess of both.)

如果没有同步,就不能保证读取和写入的顺序,可能会使变量成为垃圾。
(例如,一个变量可能会以一个线程写入一半的位和另一个线程写入一半的位结束,使变量处于两个线程都未尝试写入的状态,而是两者结合在一起的混乱状态。)

It is not enough to complete a write operation in a thread before (wall-clock time) another thread reads it, because hardware could have cached the value of the variable, and the reading thread would see the cached value instead of what was written to it.

在另一个线程读取它之前(挂钟时间)在一个线程中完成写入操作是不够的,因为硬件可以缓存变量的值,而读取线程将看到缓存的值而不是写入的值它。

Conclusion

结论

Thus in Java's case, you have to follow the Java Memory Model to ensure that threading errors do not happen.
In other words: Use synchronization, atomic operations or classes that use them for you under the hoods.

因此,在 Java 的情况下,您必须遵循 Java 内存模型以确保不会发生线程错误。
换句话说:使用同步、原子操作或在幕后为您使用它们的类。

Sources

http://docs.oracle.com/javase/specs/jls/se8/html/index.html
Java? Language Specification, 2015-02-13

来源

http://docs.oracle.com/javase/specs/jls/se8/html/index.html
Java?语言规范,2015-02-13