简体   繁体   English

“同步”是什么意思?

[英]What does 'synchronized' mean?

I have some questions regarding the usage and significance of the synchronized keyword.我有一些关于synchronized关键字的用法和意义的问题。

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

The synchronized keyword is all about different threads reading and writing to the same variables, objects and resources. synchronized关键字是关于读取和写入相同变量、对象和资源的不同线程。 This is not a trivial topic in Java, but here is a quote from Sun:这在 Java 中不是一个微不足道的话题,但这里引用了 Sun 的话:

synchronized methods 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.简而言之:当您有两个线程正在读取和写入同一个“资源”时,比如说一个名为foo的变量,您需要确保这些线程以原子方式访问该变量。 Without the synchronized keyword, your thread 1 may not see the change thread 2 made to foo , or worse, it may only be half changed.如果没有synchronized关键字,您的线程 1 可能看不到线程 2 对foo所做的更改,或者更糟的是,它可能只更改了一半。 This would not be what you logically expect.这不会是您在逻辑上所期望的。

Again, this is a non-trivial topic in Java.同样,这在 Java 中是一个重要的话题。 To learn more, explore topics here on SO and the Interwebs about:要了解更多信息,请在 SO 和 Internet 上探索有关以下内容的主题:

Keep exploring these topics until the name "Brian Goetz" becomes permanently associated with the term "concurrency" in your brain.继续探索这些主题,直到“Brian Goetz”这个名字在你的大脑中与术语“并发”永久关联。

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: synchronized blocks the next thread's call to method test() as long as the previous thread's execution is not finished.注意:只要前一个线程的执行没有完成, synchronized阻塞下一个线程对 test() 方法的调用。 Threads can access this method one at a time.线程可以一次访问一个方法。 Without synchronized all threads can access this method simultaneously.在没有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

The synchronized keyword prevents concurrent access to a block of code or object by multiple threads. synchronized关键字可防止多个线程同时访问代码块或对象。 All the methods of Hashtable are synchronized , so only one thread can execute any of them at a time. Hashtable所有方法都是synchronized ,因此一次只有一个线程可以执行它们中的任何一个。

When using non- synchronized constructs like HashMap , you must build thread-safety features in your code to prevent consistency errors.使用HashMap等非synchronized构造时,您必须在代码中构建线程安全功能以防止一致性错误。

synchronized means that in a multi threaded environment, an object having synchronized method(s)/block(s) does not let two threads to access the synchronized method(s)/block(s) of code at the same time. synchronized意味着在多线程环境中,具有synchronized方法/块的对象不会让两个线程同时访问代码的synchronized方法/块。 This means that one thread can't read while another thread updates it.这意味着一个线程无法读取而另一个线程更新它。

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, synchronized blocks does not provide benefits.但是,如果您的应用程序是单线程的,则synchronized块不会提供任何好处。

The synchronized keyword 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.最近,并发包已经发布,其中包含许多处理多线程问题的巧妙实用程序。

Overview概述

Synchronized keyword in Java has to do with thread-safety, that is, when multiple threads read or write the same variable. Java 中的 Synchronized 关键字与线程安全有关,即当多个线程读取或写入同一个变量时。
This can happen directly (by accessing the same variable) or indirectly (by using a class that uses another class that accesses the same variable).这可以直接(通过访问同一变量)或间接(通过使用使用另一个访问同一变量的类的类)发生。

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 synchronized keyword takes an Object as it's parameter (called a lock object ), which is then followed by a { block of code } .语法上, synchronized关键字将一个Object作为它的参数(称为lock object ),然后跟着一个{ block of code }

  • When execution encounters this keyword, the current thread tries to "lock/acquire/own" (take your pick) the lock object and 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 object will wait (pause their execution).一次只有一个线程可以持有锁,在此期间所有其他试图获取同一个锁对象的线程将等待(暂停它们的执行)。 The lock will be released when execution exits the synchronized code block.当执行退出同步代码块时,锁将被释放。

Synchronized methods:同步方法:

Adding synchronized keyword to a method definition is equal to the entire method body being wrapped in a synchronized code block with the lock object being this (for instance methods) and ClassInQuestion.getClass() (for class methods) .向方法定义添加synchronized关键字等于将整个方法体包装在同步代码块中,锁定对象this (对于实例方法)ClassInQuestion.getClass() (对于类方法)

- Instance method is a method which does not have static keyword. - 实例方法是一种没有static关键字的方法。
- Class method is a method which has static keyword. - 类方法是具有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.因此,在 Java 的情况下,您必须遵循 Java 内存模型以确保不会发生线程错误。
In other words: Use synchronization, atomic operations or classes that use them for you under the hoods.换句话说:使用同步、原子操作或在幕后为您使用它们的类。

Sources来源

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

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.所有想通过的人都可以,但他们可能必须等到他们能够通过。

What is the synchronized keyword?什么是同步关键字?

Threads communicate primarily by sharing access to fields and the objects reference fields refer to.线程主要通过共享对字段和引用字段所引用的对象的访问来进行通信。 This form of communication is extremely efficient, but makes two kinds of errors possible: thread interference and memory consistency errors .这种形式的通信非常有效,但可能导致两种错误:线程干扰和内存一致性错误 The tool needed to prevent these errors is synchronization.防止这些错误所需的工具是同步。

Synchronized blocks or methods prevents thread interference and make sure that data is consistent.同步块或方法可防止线程干扰并确保数据一致。 At any point of time, only one thread can access a synchronized block or method ( critical section ) by acquiring a lock.在任何时候,只有一个线程可以通过获取锁来访问同步块或方法(临界区)。 Other thread(s) will wait for release of lock to access critical section .其他线程将等待释放锁以访问临界区

When are methods synchronized?方法何时同步?

Methods are synchronized when you add synchronized to method definition or declaration.当您将synchronized添加到方法定义或声明时,方法是同步的。 You can also synchronize a particular block of code with-in a method.您还可以在方法中同步特定的代码块。

What does it mean pro grammatically and logically?它在语法和逻辑上是什么意思?

It means that only one thread can access critical section by acquiring a lock.这意味着只有一个线程可以通过获取锁来访问临界区 Unless this thread release this lock, all other thread(s) will have to wait to acquire a lock.除非此线程释放此锁,否则所有其他线程都必须等待获取锁。 They don't have access to enter critical section with out acquiring lock.他们没有获得锁就无法进入临界区

This can't be done with a magic.这是魔法无法做到的。 It's programmer responsibility to identify critical section(s) in application and guard it accordingly.识别应用程序中的关键部分并相应地保护它是程序员的责任。 Java provides a framework to guard your application, but where and what all sections to be guarded is the responsibility of programmer. Java 提供了一个框架来保护您的应用程序,但是要保护所有部分的位置和内容是程序员的责任。

More details from java documentation page来自 java 文档页面的更多详细信息

Intrinsic Locks and Synchronization:内在锁和同步:

Synchronization is built around an internal entity known as the intrinsic lock or monitor lock.同步是围绕称为内在锁或监视器锁的内部实体构建的。 Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.内在锁在同步的两个方面都发挥作用:强制对对象状态进行独占访问并建立对可见性至关重要的发生前关系。

Every object has an intrinsic lock associated with it .每个对象都有一个与之关联的内在锁 By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them.按照惯例,需要对对象字段进行独占且一致访问的线程必须在访问对象之前获取对象的内在锁,然后在访问完成后释放内在锁。

A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock.线程在获取锁和释放锁之间被称为拥有内在锁。 As long as a thread owns an intrinsic lock, no other thread can acquire the same lock.只要一个线程拥有一个内在锁,其他线程就不能获得相同的锁。 The other thread will block when it attempts to acquire the lock.另一个线程在尝试获取锁时会阻塞。

When a thread releases an intrinsic lock, a happens-before relationship is established between that action and any subsequent acquisition of the same lock.当一个线程释放一个内在锁时,在该操作和相同锁的任何后续获取之间建立了一个happens-before 关系。

Making 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.这保证了对象状态的更改对所有线程都是可见的。

Look for other alternatives to synchronization in :在 中寻找同步的其他替代方案:

Avoid synchronized(this) in Java? 在 Java 中避免同步(这个)?

Synchronized normal method equivalent to Synchronized statement (use this) Synchronized normal method等效于Synchronized statement (使用这个)

class A {
    public synchronized void methodA() {
        // all function code
    }

    equivalent to

    public void methodA() {
        synchronized(this) {
             // all function code
        }
    } 
}

Synchronized static method equivalent to Synchronized statement (use class) Synchronized static method等价于Synchronized statement (使用类)

class A {
    public static synchronized void methodA() {
        // all function code
    }

    equivalent to

    public void methodA() {
        synchronized(A.class) {
             // all function code
        }
    } 
}

Synchronized statement (using variable)同步语句(使用变量)

class A {
    private Object lock1 = new Object();

    public void methodA() {
        synchronized(lock1 ) {
             // all function code
        }
    } 
}

For synchronized , we have both Synchronized Methods and Synchronized Statements .对于synchronized ,我们有Synchronized MethodsSynchronized Statements However, Synchronized Methods is similar to Synchronized Statements so we just need to understand Synchronized Statements .但是, Synchronized Methods类似于Synchronized Statements因此我们只需要了解Synchronized Statements

=> Basically, we will have => 基本上,我们将有

synchronized(object or class) { // object/class use to provides the intrinsic lock
   // code 
}

Here is 2 think that help understanding synchronized这里有 2 认为有助于理解synchronized

  • Every object/class have an intrinsic lock associated with it.每个对象/类都有一个与之关联的intrinsic lock
  • When a thread invokes a synchronized statement , it automatically acquires the intrinsic lock for that synchronized statement's object and releases it when the method returns.当线程调用synchronized statement ,它会自动获取该synchronized statement's对象的intrinsic lock ,并在方法返回时释放它。 As long as a thread owns an intrinsic lock , NO other thread can acquire the SAME lock => thread safe.只要一个线程拥有一个intrinsic lock其他线程就不能获得SAME锁 => 线程安全。

=> When a thread A invokes synchronized(this){// code 1} => all the block code (inside class) where have synchronized(this) and all synchronized normal method (inside class) is locked because SAME lock. => 当thread A调用synchronized(this){// code 1} => 所有具有synchronized(this)的块代码(类内部synchronized(this)和所有synchronized normal method (类内部)都被锁定,因为SAME锁。 It will execute after thread A unlock ("// code 1" finished).它将在thread A解锁(“// 代码 1”完成)后执行。

This behavior is similar to synchronized(a variable){// code 1} or synchronized(class) .这种行为类似于synchronized(a variable){// code 1}synchronized(class)

SAME LOCK => lock (not depend on which method? or which statements?) SAME LOCK => lock(不依赖于哪种方法?或哪些语句?)

Use synchronized method or synchronized statements?使用同步方法还是同步语句?

I prefer synchronized statements because it is more extendable.我更喜欢synchronized statements因为它更易于扩展。 Example, in future, you only need synchronized a part of method.例如,将来,您只需要同步方法的一部分。 Example, you have 2 synchronized method and it don't have any relevant to each other, however when a thread run a method, it will block the other method (it can prevent by use synchronized(a variable) ).例如,您有 2 个同步方法,并且它们之间没有任何相关性,但是当一个线程运行一个方法时,它会阻塞另一个方法(它可以通过使用synchronized(a variable)来阻止)。

However, apply synchronized method is simple and the code look simple.但是,apply synchronized 方法很简单,代码看起来也很简单。 For some class, there only 1 synchronized method, or all synchronized methods in the class in relevant to each other => we can use synchronized method to make code shorter and easy to understand对于某些类,只有 1 个同步方法,或者类中的所有同步方法都相互关联 => 我们可以使用synchronized method使代码更短且易于理解

Note笔记

(it not relevant to much to synchronized , it is the different between object and class or none-static and static). (它与synchronized不大,它是对象和类或非静态和静态之间的区别)。

  • When you use synchronized or normal method or synchronized(this) or synchronized(non-static variable) it will synchronized base on each object instance.当您使用synchronized或普通方法或synchronized(this)synchronized(non-static variable) ,它将基于每个对象实例进行同步。
  • When you use synchronized or static method or synchronized(class) or synchronized(static variable) it will synchronized base on class当您使用synchronized或静态方法或synchronized(class)synchronized(static variable) ,它将基于类进行同步

Reference参考

https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

Hope it help希望有帮助

Here is an explanation from The Java Tutorials .这是The Java Tutorials的解释。

Consider the following code:考虑以下代码:

 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:如果countSynchronizedCounter的实例,则使这些方法同步有两个效果:

  • 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.这保证了对象状态的更改对所有线程都是可见的。

To my understanding synchronized basically means that the compiler write a monitor.enter and monitor.exit around your method.根据我的理解,同步基本上意味着编译器围绕您的方法编写一个 monitor.enter 和 monitor.exit。 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).因此,它可能是线程安全的,具体取决于它的使用方式(我的意思是,您可以使用同步方法编写一个对象,而这些方法不是线程安全的,具体取决于您的类的功能)。

What the other answers are missing is one important aspect: memory barriers .其他答案所缺少的是一个重要方面:内存屏障 Thread synchronization basically consists of two parts: serialization and visibility.线程同步基本上由部分组成:序列化和可见性。 I advise everyone to google for "jvm memory barrier", as it is a non-trivial and extremely important topic (if you modify shared data accessed by multiple threads).我建议大家谷歌搜索“jvm 内存屏障”,因为这是一个非常重要且极其重要的话题(如果你修改了多个线程访问的共享数据)。 Having done that, I advise looking at java.util.concurrent package's classes that help to avoid using explicit synchronization, which in turn helps keeping programs simple and efficient, maybe even preventing deadlocks.这样做之后,我建议查看 java.util.concurrent 包的类,这些类有助于避免使用显式同步,这反过来又有助于保持程序的简单和高效,甚至可以防止死锁。

One such example is ConcurrentLinkedDeque .一个这样的例子是ConcurrentLinkedDeque Together with the command pattern it allows to create highly efficient worker threads by stuffing the commands into the concurrent queue -- no explicit synchronization needed, no deadlocks possible, no explicit sleep() necessary, just poll the queue by calling take().命令模式一起,它允许通过将命令填充到并发队列中来创建高效的工作线程——不需要显式同步,没有死锁可能,不需要显式 sleep(),只需通过调用 take() 轮询队列。

In short: "memory synchronization" happens implicitly when you start a thread, a thread ends, you read a volatile variable, you unlock a monitor (leave a synchronized block/function) etc. This "synchronization" affects (in a sense "flushes") all writes done before that particular action.简而言之:“内存同步”在您启动线程、线程结束、读取易失性变量、解锁监视器(留下同步块/函数)等时隐式发生。这种“同步”影响(从某种意义上说“刷新") 在该特定操作之前完成的所有写入。 In the case of the aforementioned ConcurrentLinkedDeque , the documentation "says":在上述ConcurrentLinkedDeque的情况下,文档“说”:

Memory consistency effects: As with other concurrent collections, actions in a thread prior to placing an object into a ConcurrentLinkedDeque happen-before actions subsequent to the access or removal of that element from the ConcurrentLinkedDeque in another thread.内存一致性影响:与其他并发集合一样,在将对象放入 ConcurrentLinkedDeque 之前线程中的操作发生在另一个线程中从 ConcurrentLinkedDeque 访问或删除该元素之后的操作之前

This implicit behavior is a somewhat pernicious aspect because most Java programmers without much experience will just take a lot as given because of it.这种隐性行为是一个有点有害的方面,因为大多数没有太多经验的 Java 程序员只会因为它而接受很多。 And then suddenly stumble over this thread after Java isn't doing what it is "supposed" to do in production where there is a different work load -- and it's pretty hard to test concurrency issues.然后在 Java 没有做它在有不同工作负载的生产中“应该”做的事情之后突然偶然发现了这个线程 - 并且很难测试并发问题。

Synchronized simply means that multiple threads if associated with single object can prevent dirty read and write if synchronized block is used on particular object.同步只是意味着如果在特定对象上使用同步块,则多个线程如果与单个对象相关联,则可以防止脏读和写。 To give you more clarity , lets take an example :为了让您更清楚,让我们举个例子:

class MyRunnable implements Runnable {
    int var = 10;
    @Override
    public void run() {
        call();
    }

    public void call() {
        synchronized (this) {
            for (int i = 0; i < 4; i++) {
                var++;
                System.out.println("Current Thread " + Thread.currentThread().getName() + " var value "+var);
            }
        }
    }
}

public class MutlipleThreadsRunnable {
    public static void main(String[] args) {
        MyRunnable runnable1 = new MyRunnable();
        MyRunnable runnable2 = new MyRunnable();
        Thread t1 = new Thread(runnable1);
        t1.setName("Thread -1");
        Thread t2 = new Thread(runnable2);
        t2.setName("Thread -2");
        Thread t3 = new Thread(runnable1);
        t3.setName("Thread -3");
        t1.start();
        t2.start();
        t3.start();
    }
}

We've created two MyRunnable class objects , runnable1 being shared with thread 1 and thread 3 & runnable2 being shared with thread 2 only.我们创建了两个 MyRunnable 类对象,runnable1 与线程 1 共享,线程 3 和 runnable2 仅与线程 2 共享。 Now when t1 and t3 starts without synchronized being used , PFB output which suggest that both threads 1 and 3 simultaneously affecting var value where for thread 2 , var has its own memory.现在,当 t1 和 t3 在没有使用同步的情况下启动时,PFB 输出表明线程 1 和 3 同时影响 var 值,其中线程 2 , var 有自己的内存。

Without Synchronized keyword

    Current Thread Thread -1 var value 11
    Current Thread Thread -2 var value 11
    Current Thread Thread -2 var value 12
    Current Thread Thread -2 var value 13
    Current Thread Thread -2 var value 14
    Current Thread Thread -1 var value 12
    Current Thread Thread -3 var value 13
    Current Thread Thread -3 var value 15
    Current Thread Thread -1 var value 14
    Current Thread Thread -1 var value 17
    Current Thread Thread -3 var value 16
    Current Thread Thread -3 var value 18

Using Synchronzied, thread 3 waiting for thread 1 to complete in all scenarios.使用 Synchronzied,线程 3 在所有场景中等待线程 1 完成。 There are two locks acquired , one on runnable1 shared by thread 1 and thread 3 and another on runnable2 shared by thread 2 only.获得了两个锁,一个在线程 1 和线程 3 共享的 runnable1 上,另一个在仅由线程 2 共享的 runnable2 上。

Current Thread Thread -1 var value 11
Current Thread Thread -2 var value 11
Current Thread Thread -1 var value 12
Current Thread Thread -2 var value 12
Current Thread Thread -1 var value 13
Current Thread Thread -2 var value 13
Current Thread Thread -1 var value 14
Current Thread Thread -2 var value 14
Current Thread Thread -3 var value 15
Current Thread Thread -3 var value 16
Current Thread Thread -3 var value 17
Current Thread Thread -3 var value 18

In java to prevent multiple threads manipulating a shared variable we use synchronized keyword.在java中为了防止多个线程操作共享变量,我们使用synchronized关键字。 Lets understand it with help of the following example:让我们借助以下示例来理解它:

In the example I have defined two threads and named them increment and decrement.在示例中,我定义了两个线程并将它们命名为 increment 和 decrement。 Increment thread increases the value of shared variable ( counter ) by the same amount the decrement thread decreases it ie 5000 times it is increased (which result in 5000 + 0 = 5000) and 5000 times we decrease (which result in 5000 - 5000 = 0).递增线程增加共享变量( counter )的值与递减线程减少它的量相同,即增加 5000 倍(导致 5000 + 0 = 5000)和减少 5000 倍(导致 5000 - 5000 = 0) )。

Program without synchronized keyword:没有synchronized关键字的程序:

class SynchronizationDemo {

    public static void main(String[] args){

        Buffer buffer = new Buffer();                   

        MyThread incThread = new MyThread(buffer, "increment");
        MyThread decThread = new MyThread(buffer, "decrement"); 

        incThread.start();
        decThread.start();  
       
        try {
          incThread.join();
          decThread.join();
        }catch(InterruptedException e){ }

        System.out.println("Final counter: "+buffer.getCounter());
    }
}

class Buffer {
    private int counter = 0; 
    public void inc() { counter++; }
    public void dec() { counter--; } 
    public int getCounter() { return counter; }
}

class MyThread extends Thread {

    private String name;
    private Buffer buffer;

    public MyThread (Buffer aBuffer, String aName) {            
        buffer = aBuffer; 
        name = aName; 
    }

    public void run(){
        for (int i = 0; i <= 5000; i++){
            if (name.equals("increment"))
                buffer.inc();
            else
                buffer.dec();                           
        }
    }
}

If we run the above program we expect value of buffer to be same since incrementing and decrementing the buffer by same amount would result in initial value we started with right ?.如果我们运行上面的程序,我们期望缓冲区的值是相同的,因为以相同的量递增和递减缓冲区将导致我们从正确的?开始的初始值。 Lets see the output:让我们看看输出:

在此处输入图片说明

As you can see no matter how many times we run the program we get a different result reason being each thread manipulated the counter at the same time.正如您所看到的,无论我们运行程序多少次,我们都会得到不同的结果,原因是每个线程同时操作counter If we could manage to let the one thread to first increment the shared variable and then second to decrement it or vice versa we will then get the right result that is exactly what can be done with synchronized keyword by just adding synchronized keyword before the inc and dec methods of Buffer like this:如果我们能够设法让一个线程第一个增量共享变量,然后第二次递减,或反之,我们会再得到正确的结果,这正是是可以做到synchronized关键字只需添加synchronized关键字之前incBuffer dec方法如下:

Program with synchronized keyword:使用synchronized关键字的程序:

// rest of the code

class Buffer {
    private int counter = 0; 
    // added synchronized keyword to let only one thread
    // be it inc or dec thread to manipulate data at a time
    public synchronized void inc() { counter++; }
    public synchronized void dec() { counter--; } 
    public int getCounter() { return counter; }
}

// rest of the code

and the output:和输出:

在此处输入图片说明

no matter how many times we run it we get the same output as 0无论我们运行多少次,我们都会得到与 0 相同的输出

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()

volatile [About] => synchronized volatile [关于] => synchronized

synchronized block in Java is a monitor in multithreading. Java 中的synchronized块是多线程中的监视器。 synchronized block with the same object/class can be executed by only single thread, all others are waiting.具有相同对象/类的synchronized块只能由单个线程执行,所有其他线程都在等待。 It can help with race condition situation when several threads try to update the same variable.当多个线程尝试更新同一个变量时,它可以帮助解决race condition情况。

Java 5 extended synchronized by supporting happens-before [About] Java 5通过支持happens-before扩展了synchronized [关于]

An unlock (synchronized block or method exit) of a monitor happens-before every subsequent lock (synchronized block or method entry) of that same monitor.监视器的解锁(同步块或方法退出)发生在同一监视器的每个后续锁(同步块或方法入口)之前。

The next step is java.util.concurrent下一步是java.util.concurrent

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在Vector / ArrayList的上下文中,synchronized是什么意思? - What does synchronized mean in context of Vector / ArrayList? 当我们说 ArrayList 不同步时,这意味着什么? - What does it mean when we say an ArrayList is not synchronized? 参照Spring-Hibernate的“事务同步会话”是什么意思? - What does it mean by “Transaction Synchronized Session” with reference to Spring-Hibernate? 当我们说Hashtable或Vector是同步的时候意味着什么? - What does it mean when we say Hashtable or Vector is synchronized? 当我们说同步(实例字段)时,它意味着什么? - what does it mean when we say synchronized(instance field)..? 与“this”实例不同,在不同的监视器上建立同步块意味着什么? - What does it mean to have a synchronized block on a different monitor than 'this' instance? 当他们说StringBuffer类已同步时,这到底是什么意思? 是否已声明该类的所有方法同步? - What exactly does it mean when they say that StringBuffer class is synchronized? Are all methods of that class declared synchronized? 形式参数上的同步有什么作用? - what does synchronized on formal parameter do? 同步(类参考)有什么作用? - What does synchronized(class reference) do? 在Java &lt;= 0中是什么意思?0:1; - what does mean in java <=0?0:1;
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM