java 同步块关键字_Java同步关键字,同步方法和块

本文介绍了Java同步关键字在多线程编程中的重要性,通过示例讲解了同步块和同步方法的使用,包括它们的语法和内部工作原理,以防止数据损坏并保证线程安全。
摘要由CSDN通过智能技术生成

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同步关键字用于多线程中,以创建一个代码块,该代码块一次只能由一个线程执行。



为什么需要同步? (Why do we need Synchronization?)

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

		List<Thread> threads = 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 Thread join() method to make sure every thread is dead before we print the final count.

我们正在使用Thread join()方法来确保每个线程都已死,然后再打印最终计数。

We are also using Random class to add some processing time in the run() method.

我们还使用Random类在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关键字以在这种情况下提供帮助,方法是将代码标记为仅在任何时间点由一个线程执行。



Java同步示例 (Java synchronized Example)

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 synchronized Keyword Example

Java synchronized Keyword Example

Java同步关键字示例



同步关键字如何在内部运作? (How does synchronized keyword work internally?)

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 NullPointerException.

如果对象为“ null”,则synced关键字将抛出NullPointerException



Java同步块 (Java synchronized Block)

When a block of code is wrapped around the synchronized keyword, it's called a synchronized block.

当代码块包装在synced关键字周围时,称为同步块。

同步块的语法 (Syntax of synchronized block)

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
	}

}


Java同步方法 (Java synchronized Method)

Sometimes, every statement inside a method is required to be synchronized. In this case, we can synchronize the method itself.

有时,方法中的每个语句都需要同步。 在这种情况下,我们可以同步方法本身。

同步方法的语法 (Syntax of synchronized Method)

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;
	}

}


用同步方法锁定对象 (Lock Object in Synchronized Method)

Just like synchronized block, synchronized methods also require an object to lock.

就像同步块一样,同步方法也需要一个对象来锁定。

  • If the method is static, the lock is acquired on the class.

    如果方法是static ,则在类上获取锁。
  • If the method is non-static, the lock is acquired on the current object.

    如果该方法是非静态的,则在当前对象上获取锁定。


Java同步方法与块 (Java synchronized Method vs Block)

  • Java synchronized method locks the current object, so if there is another synchronized method then the other threads will be waiting for the lock on the object even if there is no shared variable in these methods. Java synchronized block works on an object field, so it's better to use the synchronized block in this case.

    Java同步方法将锁定当前对象,因此,如果存在另一个同步方法,那么即使这些方法中没有共享变量,其他线程也将等待该对象的锁定。 Java同步块适用于对象字段,因此在这种情况下最好使用同步块。
  • If the object has multiple synchronized methods working on the same variables, then the synchronized method is preferred. For example, StringBuffer uses synchronized methods because of all the append() and insert() methods work on the same object.

    如果对象具有在相同变量上工作的多个同步方法,则首选同步方法。 例如, StringBuffer使用同步方法,因为所有的append()和insert()方法都作用于同一对象。

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;
		}
	}
}


结论 (Conclusion)

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同步关键字对于避免多线程编程中的数据损坏很有用。 但是,由于锁定机制的额外开销,同步会降低代码的性能。 使用同步块还是同步方法在很大程度上取决于您的项目要求。

翻译自: https://www.journaldev.com/31514/java-synchronized-keyword-method-block

java 同步块关键字

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值