Java 并发中 Lock 和 Monitor 的区别
在 Java 中,并发是一种允许在单个处理器或多个处理器上同时运行多个任务或进程的技术。它可以提高应用程序的性能和响应能力。但是,它也为 Java 开发人员带来了新的挑战和复杂性,例如同步和死锁。为了处理这些复杂性,Java 提供了锁和监视器。两者相互关联,用于同步对共享资源的访问并确保线程安全。但是,在功能和用法方面,锁和监视器之间存在一些差异。
Lock 与 Monitor
监视器 (Monitor)
当我们在多线程环境中工作时,多个线程访问共享资源,我们需要某种方法来确保一次只有一个线程访问资源。因为如果我们未能建立这些线程之间的合作,可能会导致分配任务的错误结果。同步是实现此目的的方法。
同步的核心是监视器,它是一个建立互斥锁的对象。监视器就像一个同步区域,在特定时间只能被一个线程获取。
锁 (Lock)
当多个线程尝试访问共享资源时,Lock 对象通过“lock()”和“unlock()”方法限制一次只有一个线程访问。线程通过“tryLock()”方法请求获取 Lock 对象。当锁分配给它时,并在任务完成后释放锁。在资源繁忙期间,其他线程在队列中等待轮到它们。
锁允许线程独立地处理共享资源,而不会受到其他线程的干扰。此外,单个线程可以多次请求锁。
方法
创建一个名为“Thrd”的类,并在其中定义一个名为“operation()”的静态同步方法以及一个参数。
现在,在这个方法中,使用一个将运行 4 次的 for 循环执行求和运算。此循环的 try 块将以指定的时间间隔(即 1000 毫秒)打印输出。
接下来,创建三个线程。在这些线程中,将参数传递给“operation()”方法。
最后,在主方法中为线程类创建三个对象,并使用内置方法“start()”执行它们。
同步示例
以下示例演示了我们到目前为止讨论的内容。
class Thrd { public static synchronized void operation(int data) { for(int i = 1; i <= 4; i++) { int sum = i + data; System.out.println(sum); try { // each iteration performed with interval of 1 sec Thread.sleep(1000); } catch(Exception exp){} } } } class Thrd1 extends Thread { // thread number 1 public void run() { Thrd.operation(1); } } class Thrd2 extends Thread { // thread number 2 public void run() { Thrd.operation(5); } } class Thrd3 extends Thread { // thread number 3 public void run() { Thrd.operation(10); } } public class ThrdExecution { public static void main(String args[]) { // creating object for thread class Thrd1 oprt1 = new Thrd1(); Thrd2 oprt2 = new Thrd2(); Thrd3 oprt3 = new Thrd3(); // Starting the thread operation oprt1.start(); oprt2.start(); oprt3.start(); } }
输出
2 3 4 5 11 12 13 14 6 7 8 9
Lock 和 Monitor 的区别
锁 (Lock) |
监视器 (Monitor) |
---|---|
它提供了对同步的显式控制,这意味着它允许程序员显式地获取和释放它们。 |
它提供了对同步的隐式控制。它由运行时环境自动管理。 |
它比监视器使用得相对较少。 |
它被广泛使用 |
它实现起来有点复杂,但比监视器更灵活。 |
它实现起来更简单,与锁相比,灵活性较差。 |
锁可以被线程多次获取和释放。 |
线程每个资源只能使用一个监视器。 |
锁允许线程通过调用其 tryLock() 方法来检查它是否可以获取锁。 |
监视器无法做到这一点。 |
结论
在本文中,我们讨论了同步中一个非常重要的主题,它促使线程按顺序执行代码块。Lock 和 Monitor 是同步的基础。从逻辑上讲,它们之间没有区别,它们实际上是互补的。当线程获取锁时,它会进入监视器,监视器是一个同步区域。