深入理解多线程(四)— Moniter的实现原理

深入理解多线程(四)— Moniter的实现原理

深入理解多线程(一)—Synchronized的实现原理中介绍过关于Synchronize的实现原理,无论是同步方法还是同步代码块,无论是ACC_SYNCHRONIZED还是monitorenter、monitorexit都是基于Monitor实现的,接下来我们就详细介绍下什么是Monitor。

1. 操作系统中的monitors

管程(monitors)在操作系统中是很重要的概念,下面是管程的概念:
管程 (英语:Monitors,也称为监视器) 是一种程序结构,结构内的多个子程序(对象或模块)形成的多个工作线程互斥访问共享资源。这些共享资源一般是硬件设备或一群变量。管程实现了在一个时间点,最多只有一个线程在执行管程的某个子程序。与那些通过修改数据结构实现互斥访问的并发程序设计相比,管程实现很大程度上简化了程序设计。 管程提供了一种机制,线程可以临时放弃互斥访问,等待某些条件得到满足后,重新获得执行权恢复它的互斥访问。

2. java中的monitor

monitor在java同步机制中使用。在多线程访问共享资源的时候,经常会带来可见性和原子性的安全问题。为了解决这类线程安全的问题,Java提供了同步机制、互斥锁机制,这个机制保证了在同一时刻只有一个线程能访问共享资源。这个机制的保障来源于监视锁Monitor,每个对象都拥有自己的监视锁Monitor。
先来举个例子,然后我们在上源码。我们可以把监视器理解为包含一个特殊的房间的建筑物,这个特殊房间同一时刻只能有一个客人(线程)。这个房间中包含了一些数据和代码。如下图所示:
这里写图片描述
如果一个顾客想要进入这个特殊的房间,他首先需要在走廊(Entry Set)排队等待。调度器将基于某个标准(比如 FIFO)来选择排队的客户进入房间。如果,因为某些原因,该客户客户暂时因为其他事情无法脱身(线程被挂起),那么他将被送到另外一间专门用来等待的房间(Wait Set),这个房间的可以可以在稍后再次进入那件特殊的房间。如上面所说,这个建筑屋中一共有三个场所。如下图:
这里写图片描述
总之,监视器是一个用来监视这些线程进入特殊的房间的。他的义务是保证(同一时间)只有一个线程可以访问被保护的数据和代码。
Monitor其实是一种同步工具,也可以说是一种同步机制,它通常被描述为一个对象,主要特点是:
(1)对象的所有方法都被“互斥”的执行。好比一个Monitor只有一个运行“许可”,任一个线程进入任何一个方法都需要获得这个“许可”,离开时把许可归还。
(2)通常提供singnal机制:允许正持有“许可”的线程暂时放弃“许可”,等待某个谓词成真(条件变量),而条件成立后,当前进程可以“通知”正在等待这个条件变量的线程,让他可以重新去获得运行许可。

3. 监视器的实现

接下来我们首先看下在monitor在Java虚拟机(HotSpot)中的实现,其实现是基于C++的,由ObjectMonitor实现的,其主要数据结构如下:

  ObjectMonitor() {
    _header       = NULL;
    _count        = 0
  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
好的,我将为您编写一个类似于udev的程序,实现udevadm monitor的功能。以下是程序的基本框架: ```c #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/types.h> #include <linux/netlink.h> #include <linux/rtnetlink.h> #define BUFFER_SIZE 4096 int main() { int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (fd < 0) { perror("socket"); exit(1); } struct sockaddr_nl sa; memset(&sa, 0, sizeof(sa)); sa.nl_family = AF_NETLINK; sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR; if (bind(fd, (struct sockaddr*)&sa, sizeof(sa)) < 0) { perror("bind"); exit(1); } while (1) { char buffer[BUFFER_SIZE]; ssize_t len = recv(fd, buffer, BUFFER_SIZE, 0); if (len < 0) { perror("recv"); exit(1); } for (struct nlmsghdr* nlh = (struct nlmsghdr*)buffer; NLMSG_OK(nlh, len); nlh = NLMSG_NEXT(nlh, len)) { if (nlh->nlmsg_type == NLMSG_DONE) break; if (nlh->nlmsg_type == NLMSG_ERROR) { perror("NLMSG_ERROR"); exit(1); } struct ifinfomsg* ifi = (struct ifinfomsg*)NLMSG_DATA(nlh); if (ifi->ifi_family != AF_UNSPEC && ifi->ifi_family != AF_INET && ifi->ifi_family != AF_INET6) continue; printf("ACTION=%s\tDEVPATH=/devices/virtual/net/%s\n", nlh->nlmsg_type == RTM_NEWLINK ? "add" : "remove", ifi->ifi_name); } } close(fd); return 0; } ``` 该程序使用了Linux的Netlink套接字来监听内核的网络设备事件。具体来说,它监听RTMGRP_LINK、RTMGRP_IPV4_IFADDR和RTMGRP_IPV6_IFADDR三个事件组,并在接收到相应的事件时打印出类似于udevadm monitor的输出。 在程序中,我们首先创建一个Netlink套接字,并绑定到RTMGRP_LINK、RTMGRP_IPV4_IFADDR和RTMGRP_IPV6_IFADDR三个事件组。然后,我们进入一个循环,不断接收来自内核的Netlink消息,并根据消息内容打印出相应的设备事件。 需要注意的是,由于Netlink消息可能比较大,我们需要使用NLMSG_OK和NLMSG_NEXT宏来遍历消息链表。另外,我们还需要解析接收到的消息中的ifinfomsg结构体,从而获取设备的名称和状态信息。 希望这个程序能够帮助您实现类似于udevadm monitor的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值