本文共 7827 字,大约阅读时间需要 26 分钟。
java 同步块关键字
Java synchronized keyword is used in multithreading to create a code block that can be executed by only one thread at a time.
Java同步关键字用于多线程中,以创建一个代码块,该代码块一次只能由一个线程执行。
When we have multiple threads working on a shared entity, the end result might be corrupt. Let’s say we have a simple program to increase the counter variable of the object. This variable is shared across all the threads.
当我们有多个线程在一个共享实体上工作时,最终结果可能会损坏。 假设我们有一个简单的程序来增加对象的计数器变量。 该变量在所有线程之间共享。
package com.journaldev.threads;import java.util.ArrayList;import java.util.List;import java.util.Random;public class CounterThread implements Runnable { private int count; public int getCount() { return count; } public void setCount(int count) { this.count = count; } @Override public void run() { Random rand = new Random(); try { Thread.sleep(rand.nextInt(1000)); } catch (InterruptedException e) { e.printStackTrace(); } count++; } public static void main(String[] args) throws InterruptedException { CounterThread ct = new CounterThread(); Listthreads = new ArrayList<>(); for (int i = 0; i < 100; i++) { Thread t = new Thread(ct); threads.add(t); t.start(); } // wait for every thread to finish for (Thread t : threads) { t.join(); } System.out.println("Final Count = " + ct.getCount()); }}
We are using to make sure every thread is dead before we print the final count.
我们正在使用来确保每个线程都已死,然后再打印最终计数。
We are also using to add some processing time in the run() method.
我们还使用在run()方法中添加一些处理时间。
If you run the above program, you will notice that the final count varies almost every time.
如果您运行上述程序,您会发现最终计数几乎每次都不同。
The reason for this variance is the "count++" statement. It's not an atomic operation.
这种差异的原因是“ count ++”语句。 这不是原子操作。
The count variable is read first, then 1 is added to it and then the value is assigned back to the count variable.
首先读取count变量,然后将其添加1,然后将值分配回count变量。
We have multiple threads working on the count variable at the same time. If a thread reads the count variable and before it can update it, another thread updates it. This will cause data corruption in our program.
我们有多个线程同时处理count变量。 如果一个线程读取了count变量并且在可以更新它之前,另一个线程将对其进行更新。 这将导致程序中的数据损坏。
Java provides the synchronized keyword to help in this scenario by marking the code to be executed by one thread only at any point in time.
Java提供了synced关键字以在这种情况下提供帮助,方法是将代码标记为仅在任何时间点由一个线程执行。
Let's fix the above program using the synchronized keyword. We can create a synchronized block around the "count++" operation.
让我们使用synced关键字修复以上程序。 我们可以围绕“ count ++”操作创建一个同步块。
The synchronized keyword requires an object argument that will be used to create the locking mechanism. We can create a dummy object in the class for this purpose.
synced关键字需要一个对象参数,该参数将用于创建锁定机制。 为此,我们可以在类中创建一个虚拟对象。
Below is the updated code that will work fine and the final count will be 100. I have removed the common code so that the focus remains only on the synchronized keyword usage.
下面是更新的代码,该代码可以正常工作,最终计数为100。我删除了通用代码,因此重点仅放在同步关键字的用法上。
public class CounterThread implements Runnable {... private final Object mutex = new Object();... public void run() {... synchronized (mutex) { count++; } }...}
Java synchronization logic is built around an internal entity called an intrinsic lock or monitor lock.
Java同步逻辑围绕称为内部锁或监视器锁的内部实体构建。
When a thread tries to enter a synchronized area, it has to first acquire the lock on the object. Then all the statements in the synchronized block are executed. Finally, the thread releases the lock on the object that can be acquired by other threads in the wait pool.
当线程尝试进入同步区域时,它必须首先获取对象上的锁。 然后执行同步块中的所有语句。 最后,线程释放对象上的锁,等待池中的其他线程可以获取该锁。
If the object is "null", the synchronized keyword will throw .
如果对象为“ null”,则synced关键字将抛出 。
When a block of code is wrapped around the synchronized keyword, it's called a synchronized block.
当代码块包装在synced关键字周围时,称为同步块。
synchronized (object) { // syhcnronized block code}
Here is a simple example of a synchronized block in Java.
这是Java中同步块的简单示例。
package com.journaldev.threads;public class MyRunnable implements Runnable { private int counter; private final Object mutex = new Object(); @Override public void run() { doSomething(); synchronized (mutex) { counter++; } } private void doSomething() { // some heavy lifting work }}
Sometimes, every statement inside a method is required to be synchronized. In this case, we can synchronize the method itself.
有时,方法中的每个语句都需要同步。 在这种情况下,我们可以同步方法本身。
access_modifiers synchronized return_type method_name(method_parameters) { method_code}
Here is an example of java synchronized method.
这是一个Java同步方法的示例。
package com.journaldev.threads;public class MyRunnable implements Runnable { private int counter; @Override public void run() { increment(2); } private synchronized void increment(int i) { counter += i; }}
Just like synchronized block, synchronized methods also require an object to lock.
就像同步块一样,同步方法也需要一个对象来锁定。
Here is an example where we have multiple methods working on the same variable, so using the synchronized method is a better choice.
这是一个示例,其中我们有多个方法作用于同一变量,因此使用同步方法是一个更好的选择。
package com.journaldev.threads;public class MyRunnable implements Runnable { private int counter; @Override public void run() { increment(2); decrement(1); } private synchronized void increment(int i) { counter += i; } private synchronized void decrement(int i) { counter -= i; }}
Here is another example where the different methods are working on a different shared variable, so using a synchronized block is a better choice.
这是另一个示例,其中不同的方法正在不同的共享变量上工作,因此使用同步块是更好的选择。
package com.journaldev.threads;public class MyRunnable implements Runnable { private int positiveCounter; private int negativeCounter; private final Object positiveCounterMutex = new Object(); private final Object negativeCounterMutex = new Object(); @Override public void run() { increment(2); decrement(1); } private void increment(int i) { synchronized (positiveCounterMutex) { positiveCounter += i; } } private void decrement(int i) { synchronized (negativeCounterMutex) { negativeCounter -= i; } }}
Java synchronized keyword is useful in avoiding data corruption in multithreaded programming. However, synchronization reduces the performance of the code because of the extra overhead of locking mechanism. Whether to use a synchronized block or synchronized method depends a lot on your project requirements.
Java同步关键字对于避免多线程编程中的数据损坏很有用。 但是,由于锁定机制的额外开销,同步会降低代码的性能。 使用同步块还是同步方法在很大程度上取决于您的项目要求。
翻译自:
java 同步块关键字
转载地址:http://lqlzd.baihongyu.com/