Java 中的对象级锁与类级锁

位置:首页>文章>详情   分类: Java教程 > 编程技术   阅读(279)   2023-06-26 07:54:18

在 Java 中,同步 代码块一次只能由一个线程执行。另外,java支持多线程并发执行。这可能会导致两个或多个线程同时访问相同的字段或对象。

同步是使执行中的所有并发线程保持同步的过程。同步避免了由于共享内存视图不一致而导致的内存一致性错误。当方法声明为同步时;该线程持有该方法对象的监视器或锁定对象。如果另一个线程正在执行 synchronized 方法,您的线程将被阻塞,直到该线程释放监视器。

请注意,我们可以在定义的方法或块的类中使用 synchronized 关键字。 synchronized 关键字不能与类定义中的变量或属性一起使用。

1. Java中的对象级锁

对象级锁是一种机制,当我们想要同步一个非静态方法非静态代码块时,只有一个线程能够在类的给定实例上执行代码块。应始终这样做以使实例级数据线程安全

对象级锁定可以按如下方式完成:

public class DemoClass
{
	public synchronized void demoMethod(){}
}

or

public class DemoClass
{
	public void demoMethod(){
		synchronized (this)
		{
			//other thread safe code
		}
	}
}

or

public class DemoClass
{
	private final Object lock = new Object();
	public void demoMethod(){
		synchronized (lock)
		{
			//other thread safe code
		}
	}
}

2. Java中的类级锁

类级别锁 可防止多个线程在运行时进入该类所有可用实例中的任何一个的synchronized 块中。这意味着如果在运行时有 100 个 DemoClass 实例,那么一次只有一个线程能够在任何一个实例中执行 demoMethod(),并且所有其他实例都将被其他线程锁定。

应始终执行类级锁定以使静态数据线程安全。我们知道 static 关键字将方法的数据关联到类级别,因此在静态字段或方法上使用锁定使其在类级别。

public class DemoClass
{
	//Method is static
	public synchronized static void demoMethod(){

	}
}

or

public class DemoClass
{
	public void demoMethod()
	{
		//Acquire lock on .class reference
		synchronized (DemoClass.class)
		{
			//other thread safe code
		}
	}
}

or

public class DemoClass
{
	private final static Object lock = new Object();

	public void demoMethod()
	{
		//Lock object is static
		synchronized (lock)
		{
			//other thread safe code
		}
	}
}

3. 对象级锁与类级锁——重要说明

  1. Java 中的同步保证没有两个线程可以同时或同时执行需要相同锁的同步方法。
  2. synchronized 关键字只能与方法和代码块一起使用。这些方法或块可以是静态非静态
  3. 当线程进入 Java synchronized 方法或阻塞时,它会获得一个锁,而每当它离开同步方法或阻塞时,它就会释放锁。即使线程在完成后或由于任何错误或异常而离开同步方法,锁也会被释放。
  4. Java synchronized 关键字本质上是可重入 这意味着如果一个同步方法调用另一个需要相同锁的同步方法,那么持有锁的当前线程可以在不获取锁的情况下进入该方法。
  5. 如果同步块中使用的对象为空,则 Java 同步将抛出 NullPointerException。例如,在上面的代码示例中,如果锁被初始化为 null,则“synchronized (lock)”将抛出 NullPointerException
  6. Java 中的同步方法会给您的应用程序带来性能成本。因此,在绝对需要时使用同步。此外,考虑使用同步代码块来仅同步代码的关键部分。
  7. 有可能静态同步和非静态同步方法可以同时或并发运行,因为它们锁定不同的对象。
  8. 根据 Java 语言规范,您不能在构造函数中使用 synchronized 关键字。这是非法的,会导致编译错误。
  9. 不要在 Java 同步块的非最终字段上进行同步。因为非 final 字段的引用可能随时更改,然后不同的线程可能会在不同的对象上同步,即根本没有同步。
  10. 不要使用字符串字面值,因为它们可能会在应用程序的其他地方被引用,并可能导致死锁。可以安全地使用使用 new 关键字创建的字符串对象。但作为最佳实践,创建一个新的 private 作用域 Object 实例或锁定我们要保护的共享变量本身。 [感谢 Anu 在评论中指出这一点。]

让我知道有关 Java 中对象级锁与类级锁的想法和疑问。

快乐学习!!

地址:https://www.cundage.com/article/object-vs-class-level-locking.html

相关阅读

我们已经知道关于 线程同步 以及使用同步 关键字的各种机制。 Java 提供了另一种基于 Lock 接口和实现它的类(例如 ReentrantLock).在本教程中,我们将看到 Lock 接口的...
在 Java 中,同步 代码块一次只能由一个线程执行。另外,java支持多线程并发执行。这可能会导致两个或多个线程同时访问相同的字段或对象。 同步是使执行中的所有并发线程保持同步的过程。同步避免...
通过示例学习以编程方式在 Java 中创建死锁。此外,学习在源代码中检测死锁以及如何解决死锁情况。 一般情况下,如果程序同步不当,系统资源在线程之间共享,那么总是有可能出现死锁情况,即多个线程等...
根据 java 文档,CountDownLatch 是一种同步辅助工具,它允许一个或多个线程等待,直到其他线程中执行的一组操作完成。 CountDownLatch 概念是 java concur...
了解 Java 中 sleep() 和 wait() 方法的区别。了解何时使用哪种方法以及它们在 Java 并发 中带来的影响。 1. Java sleep() 和 wait() – 讨论 sl...
简单来说,空间就是运行的能力几个程序或一个程序的几个部分并行。并发使程序能够通过利用底层操作系统和机器硬件的未开发功能来实现高性能和吞吐量。例如,现代计算机有多个 CPU 或一个 CPU 中包含...
在 JDK 8 之前,无法在 Java 中创建大型、线程安全的 ConcurrentHashSet。 java.util.concurrent 包甚至没有名为 ConcurrentHashSet...
如果您使用的是纯 Java,从版本 5 开始,我们有一个方便的调度程序类,允许以固定速率或固定延迟运行任务: import java.util.concurrent.Executors; imp...
我们的一位读者 Anant 问了这个非常好的问题,详细说明/列出了我们应该了解的关于多线程的所有相关主题,包括 Java 8 中所做的更改。(初级到高级)。他只想知道 Java 中多线程框架的演...
Java HashMap 默认是不同步的。如果我们在多个线程正在添加和删除对的并发应用程序中从 HashMap 添加/删除键值对,我们最终可能会出现不一致的映射状态。学习同步 hashmap 和...