Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中,监视器和锁的区别是什么_Java_Locking_Synchronized - Fatal编程技术网

在Java中,监视器和锁的区别是什么

在Java中,监视器和锁的区别是什么,java,locking,synchronized,Java,Locking,Synchronized,使用synchronized关键字方法,使用javap命令查看字节码,发现使用了monitor,如果在实现synchronized时可以调用monitor,这是我的理解,对吗?如果不正确,请更正它。他们之间的关系是什么?锁和监视器之间的关系是什么?在中,您可以找到问题的答案: 同步。Java编程语言提供了多种 线程间通信的机制。其中最基本的 方法是同步,使用监视器实现。每个 Java中的对象与监视器关联,监视器是线程 可以锁定或解锁 从官方文件: 同步是围绕一个称为内在锁或监视锁的内部实体构建

使用synchronized关键字方法,使用javap命令查看字节码,发现使用了monitor,如果在实现synchronized时可以调用monitor,这是我的理解,对吗?如果不正确,请更正它。他们之间的关系是什么?锁和监视器之间的关系是什么?

在中,您可以找到问题的答案:

同步。Java编程语言提供了多种 线程间通信的机制。其中最基本的 方法是同步,使用监视器实现。每个 Java中的对象与监视器关联,监视器是线程 可以锁定或解锁


从官方文件:

  • 同步是围绕一个称为内在锁监视锁的内部实体构建的。(API规范通常将该实体简单地称为“监视器”)
  • 每个对象都有一个与之关联的内在锁。按照惯例,线程必须获取对象的监视器锁 在访问它们之前,然后在关闭时释放监视器锁 他们完了。一个线程被称为在两个时间间隔内拥有锁 已获取锁并释放锁。只要线程拥有 一个监视器锁,没有其他线程可以获得相同的锁。其他的 线程在尝试获取锁时将阻塞
  • 当一个线程释放锁时,在该操作和任何后续的数据获取之间建立关系之前,会发生一个错误 同样的锁

因此,不能将显示器和锁进行比较,它们是互补的。Java中的每个对象都与一个监视器相关联,线程可以锁定该监视器或解锁该监视器

锁是一种数据,在逻辑上是堆内存中对象头的一部分。JVM中的每个对象都有这个锁(或互斥锁),任何程序都可以使用它来协调对该对象的多线程访问。如果任何线程想要访问该对象的实例变量;然后线程必须“拥有”对象的锁(在锁内存区域中设置一些标志)。尝试访问对象变量的所有其他线程都必须等待,直到所属线程释放对象的锁(取消设置标志)

一旦一个线程拥有一个锁,它可以多次再次请求同一个锁,但是在其他线程可以使用该锁之前,它必须释放相同次数的锁。例如,如果一个线程请求锁三次,该线程将继续拥有该锁,直到它“释放”它三次

请注意,当线程显式请求锁时,锁是由线程获取的。在Java中,这是通过synchronized关键字或wait和notify完成的

监视器

Monitor是一种同步结构,它允许线程具有互斥(使用锁)和协作,即使线程等待特定条件为真(使用等待集)的能力

换句话说,除了实现锁的数据外,每个Java对象在逻辑上都与实现等待集的数据相关联。锁帮助线程在共享数据上独立工作而不相互干扰,而等待集则帮助线程相互协作以共同实现一个目标,例如,所有等待的线程都将移动到此等待集,一旦释放锁,所有等待的线程都将收到通知。此等待集有助于通过锁(互斥)的额外帮助构建监视器

有关更多说明,请参阅-

文档可能不是一个很好的地方来解释锁和监视器之间的区别,尤其是它提到的术语:
内在锁
监视器锁
和简单的
监视器
,这似乎表明监视器和锁是可互换的

事实并非如此

Monitor是一种用于多线程同步的结构。它由一个锁和几个条件变量组成。条件变量是一个队列,当给定条件不符合要求时,线程可以将其置于该队列中。当条件为真时,其他一些线程可以唤醒这些线程。条件变量是帮助线程相互协作的一种方法

在简单的同步情况下,我们只使用监视器提供的锁,如以下示例:

class SimpleCase {
  int counter;

  synchronized inc() int {
    return counter++;
  }
} 
执行
inc()
的线程不需要协作,只需锁定即可使线程互斥,从而使
计数器
线程安全

而在更复杂的情况下,不仅需要互斥(mutex),还需要合作

例如,有界消费者/生产者问题:多消费者和生产者消费并向队列发送消息。需要协作,因为消息队列具有最大大小,当队列已满时,无法发送更多消息,当队列为空时,无法使用更多消息

以下是显示制作人的代码:

package monitor;

public class Producer {
    BoundedQueue queue;

    public Producer(BoundedQueue queue) {
        this.queue = queue;
    }

    public void send(int msg) throws InterruptedException {
        synchronized (queue) {
            // wait till there is room to produce
            while (queue.isFull()) {
                queue.wait();
            }

            // business logic here
            queue.add(msg);
            System.out.println("sent:" + msg + ", from:" + Thread.currentThread().getName());

            // before exit, call notify() to wake up waiting threads
            queue.notifyAll();
        }// implicit release the lock when exiting the synchronized block
    }
}
在代码中,
BoundedQueue
用作监视器,除了互斥之外,生产者和消费者还需要合作:当队列已满时,生产者需要
wait()
,当队列有可用插槽时,生产者需要在向队列发送数据后,通知生产者从等待中醒来,它还需要调用
notifyAll()
,以防消费者等待队列不为空的条件

这里,监视器提供了
等待
通知
的功能,以使线程协作

希望这能帮助您理解监视器和锁之间的区别

参考:

A是