活动介绍

AQS原理详解及其在并发编程中的应用场景分析

立即解锁
发布时间: 2024-02-19 07:02:14 阅读量: 58 订阅数: 47
PDF

Java并发编程:深入解析抽象队列同步器(AQS)及其在Lock中的应用

# 1. AQS原理概述 ## 1.1 AQS简介 在并发编程中,AQS(AbstractQueuedSynchronizer)是一个非常重要的框架,它提供了一种实现同步器的基础框架。AQS是Java中用于构建锁和其他同步器的关键组件,其核心思想是通过自旋和阻塞来实现线程之间的互斥和协作。 ## 1.2 AQS的设计初衷 AQS的设计初衷是为了提供一种灵活且高效的实现方式,使得开发者能够更加方便地构建各种同步机制,如ReentrantLock、Semaphore、CountDownLatch等。通过AQS,我们可以实现自定义的同步器,满足不同场景下的并发需求。 ## 1.3 AQS的基本结构与原理 AQS的基本结构由两个队列组成:同步队列(Sync Queue)和等待队列(Condition Queue)。同步队列用于存放已经获取了同步状态的线程,而等待队列用于存放因为获取不到同步状态而被阻塞的线程。AQS的原理主要通过状态的获取和释放来实现线程的同步,通过内置的CAS操作(Compare And Swap)来保证线程安全。具体来说,AQS通过acquire和release方法来控制同步状态的获取和释放,从而实现线程的阻塞和唤醒机制。 # 2. AQS在Java并发编程中的应用 在Java并发编程中,AbstractQueuedSynchronizer(AQS)是一个非常重要的框架,它提供了一种基于独占锁(Exclusive Lock)和共享锁(Shared Lock)的同步器实现。AQS的设计初衷是为了帮助开发人员更好地实现自定义的同步器,它为实现各种同步器提供了良好的基础。 ### 2.1 ReentrantLock与AQS ReentrantLock是Java中的独占锁实现,在其内部通过AQS来管理锁的获取和释放。通过AQS,ReentrantLock可以实现对锁的可重入性(即同一个线程可以多次获得同一把锁),保证线程安全的同时提高了程序的性能。 ```java import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockDemo { private static Lock lock = new ReentrantLock(); public static void main(String[] args) { new Thread(() -> { lock.lock(); try { System.out.println(Thread.currentThread().getName() + "获取了锁"); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); System.out.println(Thread.currentThread().getName() + "释放了锁"); } }).start(); new Thread(() -> { lock.lock(); try { System.out.println(Thread.currentThread().getName() + "获取了锁"); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); System.out.println(Thread.currentThread().getName() + "释放了锁"); } }).start(); } } ``` **代码总结:** 上述代码演示了ReentrantLock的基本用法,通过AQS确保了对锁的安全获取和释放。 **结果说明:** 由于是独占锁,只有一个线程可以获取到锁,另一个线程需要等待第一个线程释放锁后才能获取。 ### 2.2 Semaphore与AQS Semaphore是一个经典的并发工具,通过AQS可以方便地实现对资源访问的控制。Semaphore允许多个线程同时访问共享资源或限制同时访问的线程数量。 ```java import java.util.concurrent.Semaphore; public class SemaphoreDemo { private static Semaphore semaphore = new Semaphore(2); public static void main(String[] args) { new Thread(() -> { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "获取了信号量"); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); System.out.println(Thread.currentThread().getName() + "释放了信号量"); } }).start(); new Thread(() -> { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "获取了信号量"); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); System.out.println(Thread.currentThread().getName() + "释放了信号量"); } }).start(); } } ``` **代码总结:** 上述代码展示了Semaphore的基本用法,通过AQS实现了对信号量的获取和释放控制。 **结果说明:** 由于Semaphore设置为2,可以同时有两个线程获取信号量,其他线程需要等待释放后才能获取。 ### 2.3 CountDownLatch与AQS CountDownLatch是一种非常常用的同步工具,它可以让某个线程等待直到倒计时结束。通过AQS的支持,CountDownLatch可以很方便地实现线程间等待和唤醒机制。 ```java import java.util.concurrent.CountDownLatch; public class CountDownLatchDemo { private static CountDownLatch latch = new CountDownLatch(2); public static void main(String[] args) throws InterruptedException { new Thread(() -> { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程1执行完毕"); latch.countDown(); }).start(); new Thread(() -> { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程2执行完毕"); latch.countDown(); }).start(); System.out.println("等待两个线程执行完毕"); latch.await(); System.out.println("两个线程均已执行完毕"); } } ``` **代码总结:** 上述代码展示了CountDownLatch的基本用法,通过AQS实现了等待线程执行完毕的功能。 **结果说明:** 主线程会等待两个子线程执行完毕后才继续执行。 ### 2.4 FutureTask与AQS FutureTask是一个可取消的异步计算任务,在内部使用AQS来实现任务的执行控制。FutureTask可以方便地获取计算结果或取消任务的执行。 ```java import java.util.concurrent.FutureTask; public class FutureTaskDemo { public static void main(String[] args) throws Exception { FutureTask<Integer> futureTask = new FutureTask<>(() -> { Thread.sleep(2000); return 1; }); new Thread(futureTask).start(); System.out.println("正在执行任务..."); System.out.println("任务执行结果为:" + futureTask.get()); } } ``` **代码总结:** 上述代码展示了FutureTask的基本用法,通过AQS实现了异步计算任务的控制和获取结果。 **结果说明:** 主线程会等待任务执行完毕,并获取到任务的结果值。 通过以上示例,我们可以看出AQS在Java并发编程中的广泛应用,帮助开发人员更加方便地实现各种同步工具和异步任务控制。 # 3. AQS内部机制详解 AQS(AbstractQueuedSynchronizer)是Java中用于构建锁和同步器的框架,它是实现各种并发锁和相关操作的基础。在这一章节中,我们将深入探讨AQS的内部机制,包括同步队列与等待队列、AQS中的状态控制以及AQS中的同步器 acquire 和 release 方法的实现原理。 #### 3.1 同步队列与等待队列 在AQS中,同步队列(Sync Queue)是一个FIFO双向队列,用于存储获取锁失败的线程。而等待队列(Wait Queue)则是一个Condition队列,用于存储调用Condition的await方法后进入等待状态的线程。 当一个线程无法获取锁时,会被包装成为一个节点(Node)并加入同步队列中。当释放锁时,会唤醒同步队列中第一个节点,使其再次尝试获取锁。如果获取失败,则会转移到等待队列中。 #### 3.2 AQS中的状态控制 AQS通过一个整型的状态变量来控制同步状态,通过getState、setState和compareAndSetState方法对其进行操作。在AQS中,状态值的具体含义由自定义的同步器来决定,可以表示某个线程是否持有锁、计数器的值等等。 #### 3.3 AQS中的同步器 acquire 和 release 在AQS中,acquire和release是两个关键的方法,用于实现获取锁和释放锁的操作。当一个线程需要获取锁时,会调用acquire方法,如果获取失败则会进入等待队列并阻塞。而当线程释放锁时,会调用release方法,唤醒等待队列中的线程来竞争锁。 以上就是AQS内部机制的详细解析,下一章节将讨论如何自定义一个AQS的同步组件,敬请期待。 如果有其他需求或问题,欢迎继续提出哦。 # 4. AQS自定义同步组件 在第四章中,我们将深入探讨如何自定义一个AQS的同步组件,并结合实例分析自定义的读写锁的实现。下面我们将逐步展开讨论。 #### 4.1 如何自定义一个AQS的同步组件 要自定义一个AQS的同步组件,需要继承`AbstractQueuedSynchronizer`类,并实现至少以下两个方法:`tryAcquire(int arg)`和`tryRelease(int arg)`。下面是一个简单的自定义同步组件的示例代码: ```java import java.util.concurrent.locks.AbstractQueuedSynchronizer; public class CustomSync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 1L; private boolean isLocked = false; @Override protected boolean tryAcquire(int arg) { if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } @Override protected boolean tryRelease(int arg) { setExclusiveOwnerThread(null); setState(0); return true; } public void lock() { acquire(1); } public void unlock() { release(1); } public boolean isLocked() { return isLocked; } } ``` 在上面的示例中,我们定义了一个简单的自定义同步组件`CustomSync`,通过继承`AbstractQueuedSynchronizer`类并实现`tryAcquire`和`tryRelease`方法,来实现自定义的加锁和解锁逻辑。 #### 4.2 实例分析:自定义的读写锁 下面我们以自定义的读写锁为例,来演示如何通过AQS来实现一个自定义的同步组件。 ```java import java.util.concurrent.locks.AbstractQueuedSynchronizer; public class CustomReadWriteLock { private final Sync sync; public CustomReadWriteLock() { this.sync = new Sync(); } static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 1L; protected boolean isWriteLock() { return getState() == -1; } protected boolean tryAcquire(int acquires) { if (isWriteLock() || Thread.currentThread() == getExclusiveOwnerThread()) { int c = getState(); if (c == 0 || (c < 0 && Thread.currentThread() == getExclusiveOwnerThread())) { if (compareAndSetState(c, c + acquires)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } } } return false; } protected boolean tryRelease(int releases) { if (!isWriteLock()) { throw new UnsupportedOperationException(); } int nextc = getState() - releases; setState(nextc); if (nextc == 0) { setExclusiveOwnerThread(null); return true; } return false; } } public void writeLock() { sync.acquire(-1); } public void writeUnlock() { sync.release(-1); } public void readLock() { sync.acquire(1); } public void readUnlock() { sync.release(1); } } ``` 在这个自定义的读写锁实现中,我们使用了一个内部类`Sync`来继承`AbstractQueuedSynchronizer`,并重写了`isWriteLock`、`tryAcquire`和`tryRelease`方法来实现特定的读写锁逻辑。通过`CustomReadWriteLock`类对外提供了读锁和写锁的获取和释放方法。 以上就是关于如何自定义一个AQS的同步组件以及实例分析自定义的读写锁的内容。 # 5. AQS在并发编程中的应用场景分析 在本章中,我们将详细分析AQS在并发编程中的几个常见应用场景,并深入探讨它们的实现原理和使用方式。通过对这些场景的分析,我们可以更好地理解AQS的强大之处,并在实际开发中选用合适的并发工具来提高程序的效率和性能。 **5.1 有界队列的实现** 在多线程编程中,有界队列是一种常见的数据结构,它可以用来实现生产者消费者模式。AQS提供了Condition和ReentrantLock来支持有界队列的实现。 ```java // Java代码示例 import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class BoundedQueue { private Object[] items; private ReentrantLock lock = new ReentrantLock(); private Condition notEmpty = lock.newCondition(); private Condition notFull = lock.newCondition(); private int count; private int putIndex; private int takeIndex; public BoundedQueue(int size) { items = new Object[size]; } public void put(Object x) throws InterruptedException { lock.lock(); try { while (count == items.length) { notFull.await(); } items[putIndex] = x; if (++putIndex == items.length) { putIndex = 0; } ++count; notEmpty.signal(); } finally { lock.unlock(); } } public Object take() throws InterruptedException { lock.lock(); try { while (count == 0) { notEmpty.await(); } Object x = items[takeIndex]; items[takeIndex] = null; if (++takeIndex == items.length) { takeIndex = 0; } --count; notFull.signal(); return x; } finally { lock.unlock(); } } } ``` 上述代码展示了利用AQS的Condition和ReentrantLock来实现一个简单的有界队列的例子。通过使用Condition,我们可以精确控制队列的状态,并在特定条件下进行等待和唤醒操作,而ReentrantLock则提供了对队列的基本锁定操作。 **5.2 线程池的原理与实现** 线程池作为一种重要的并发编程工具,在AQS的支持下得到了广泛的应用。通过AQS提供的同步机制,我们可以实现一个简单的线程池,来管理和复用线程资源。 ```java // Java代码示例 import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class CustomThreadPool { private final int nThreads; private final PoolWorker[] threads; private final BlockingQueue<Runnable> queue; public CustomThreadPool(int nThreads) { this.nThreads = nThreads; queue = new LinkedBlockingQueue<>(); threads = new PoolWorker[nThreads]; for (int i = 0; i < nThreads; i++) { threads[i] = new PoolWorker(); threads[i].start(); } } public void execute(Runnable task) { synchronized (queue) { queue.add(task); queue.notify(); } } private class PoolWorker extends Thread { public void run() { Runnable task; while (true) { synchronized (queue) { while (queue.isEmpty()) { try { queue.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } task = queue.poll(); } try { task.run(); } catch (RuntimeException e) { e.printStackTrace(); } } } } } ``` 上述代码展示了如何利用AQS实现一个简易的线程池。通过使用AQS的同步机制,我们可以实现对任务的排队和线程池线程的复用,从而提高程序的并发性能和效率。 **5.3 并发访问控制** AQS提供了灵活的同步机制,可以用于实现并发访问控制,保证多个线程对共享资源的安全访问。比如可以利用AQS来实现读写锁,Semaphore等同步工具,这些工具都是基于AQS实现的,可以有效地控制并发访问。 通过上述几种应用场景的分析,我们可以看到AQS在并发编程中的重要性和灵活性。在实际开发中,合理利用AQS可以帮助我们更好地理解并发编程的原理,并且提高程序的并发性能和安全性。 希望通过上述内容能够帮助您更好地理解AQS在并发编程中的应用场景,如果有任何疑问或者需要进一步了解的地方,欢迎随时交流讨论。 # 6. AQS的局限性与优化方向分析 在使用AQS进行并发编程时,虽然AQS提供了强大的支持,但也存在一些局限性和性能瓶颈,本章将对AQS的局限性进行分析,并探讨优化方向。 ## 6.1 AQS的性能瓶颈 使用AQS的过程中,可能会出现以下一些性能瓶颈: - **竞争激烈导致的性能下降**:当同步资源的竞争激烈时,会导致大量线程在竞争同一个资源,从而降低性能。 - **线程饥饿**:如果某些线程始终无法获取到同步资源,可能会导致这些线程一直处于饥饿状态,不能正常执行。 - **锁的粒度不合理**:如果同步资源的锁粒度设计不合理,可能会导致线程在获取锁时频繁竞争,从而影响性能。 ## 6.2 AQS的局限性及解决方案 针对AQS存在的性能瓶颈和局限性,可以采取一些优化方向来改善: - **优化竞争激烈情况**: - 采用非阻塞算法:通过CAS操作(Compare and Swap)等非阻塞算法,减少对同步资源的竞争。 - 减小锁粒度:合理设计锁的粒度,尽量减少线程之间的竞争。 - **解决线程饥饿问题**: - 公平锁机制:使用公平锁可以保证等待时间较长的线程能够获得资源,避免线程饥饿现象。 - **性能调优**: - 合理设置同步资源的容量:对于一些并发量较大的场景,可以合理设置同步资源的容量,避免资源过度竞争。 ## 6.3 对AQS的未来发展方向的展望 随着并发编程需求的不断增加,AQS作为并发编程的重要组件也将不断进行优化和改进,未来可能的发展方向包括: - **更高效的并发控制机制**:优化AQS的底层实现,提升同步资源的并发性能,减少竞争情况下的性能损耗。 - **更灵活的同步策略**:提供更多种类的同步策略,满足不同应用场景下的并发需求,更加灵活多样化。 - **更好的线程调度机制**:结合操作系统的线程调度机制,进一步提高线程的调度效率,优化并发程序的执行效率。 总的来说,AQS作为Java并发编程的核心组件,在未来的发展中将继续发挥重要作用,并不断优化和完善,以更好地满足不同并发编程场景下的需求。
corwn 最低0.47元/天 解锁专栏
赠100次下载
继续阅读 点击查看下一篇
profit 400次 会员资源下载次数
profit 300万+ 优质博客文章
profit 1000万+ 优质下载资源
profit 1000万+ 优质文库回答
复制全文

相关推荐

SW_孙维

开发技术专家
知名科技公司工程师,开发技术领域拥有丰富的工作经验和专业知识。曾负责设计和开发多个复杂的软件系统,涉及到大规模数据处理、分布式系统和高性能计算等方面。
最低0.47元/天 解锁专栏
赠100次下载
百万级 高质量VIP文章无限畅学
千万级 优质资源任意下载
千万级 优质文库回答免费看
专栏简介
本专栏旨在深入解析AQS(AbstractQueuedSynchronizer)的原理与应用,以帮助读者深入理解并发编程中的核心机制,提升Java高级开发技能。从AQS原理解读与多线程同步机制剖析、AQS原理深入解密与并发编程优化实战,到AQS原理详解及其在Java并发编程中的实际应用探讨,专栏诸多文章将围绕AQS原理展开深入研究。通过AQS原理解析与分析,读者将深入探究重入锁原理的奥秘,以及AQS在并发编程中的应用场景与实现细节。本专栏将呈现AQS原理的重要性及其在Java高级开发中的应用价值,同时结合实际案例进行分析,助力读者在并发编程中实现高性能优化与工作原理研究。

最新推荐

【高级图像识别技术】:PyTorch深度剖析,实现复杂分类

![【高级图像识别技术】:PyTorch深度剖析,实现复杂分类](https://www.pinecone.io/_next/image/?url=https%3A%2F%2Fsiteproxy.ruqli.workers.dev%3A443%2Fhttps%2Fcdn.sanity.io%2Fimages%2Fvr8gru94%2Fproduction%2Fa547acaadb482f996d00a7ecb9c4169c38c8d3e5-1000x563.png&w=2048&q=75) # 摘要 随着深度学习技术的快速发展,PyTorch已成为图像识别领域的热门框架之一。本文首先介绍了PyTorch的基本概念及其在图像识别中的应用基础,进而深入探讨了PyTorch的深度学习

分布式应用消息监控系统详解

### 分布式应用消息监控系统详解 #### 1. 服务器端ASP页面:viewAllMessages.asp viewAllMessages.asp是服务器端的ASP页面,由客户端的tester.asp页面调用。该页面的主要功能是将消息池的当前状态以XML文档的形式显示出来。其代码如下: ```asp <?xml version="1.0" ?> <% If IsObject(Application("objMonitor")) Then Response.Write cstr(Application("objMonitor").xmlDoc.xml) Else Respo

未知源区域检测与子扩散过程可扩展性研究

### 未知源区域检测与子扩散过程可扩展性研究 #### 1. 未知源区域检测 在未知源区域检测中,有如下关键公式: \((\Lambda_{\omega}S)(t) = \sum_{m,n = 1}^{\infty} \int_{t}^{b} \int_{0}^{r} \frac{E_{\alpha,\alpha}(\lambda_{mn}(r - t)^{\alpha})}{(r - t)^{1 - \alpha}} \frac{E_{\alpha,\alpha}(\lambda_{mn}(r - \tau)^{\alpha})}{(r - \tau)^{1 - \alpha}} g(\

分布式系统中的共识变体技术解析

### 分布式系统中的共识变体技术解析 在分布式系统里,确保数据的一致性和事务的正确执行是至关重要的。本文将深入探讨非阻塞原子提交(Nonblocking Atomic Commit,NBAC)、组成员管理(Group Membership)以及视图同步通信(View - Synchronous Communication)这几种共识变体技术,详细介绍它们的原理、算法和特性。 #### 1. 非阻塞原子提交(NBAC) 非阻塞原子提交抽象用于可靠地解决事务结果的一致性问题。每个代表数据管理器的进程需要就事务的结果达成一致,结果要么是提交(COMMIT)事务,要么是中止(ABORT)事务。

【PJSIP高效调试技巧】:用Qt Creator诊断网络电话问题的终极指南

![【PJSIP高效调试技巧】:用Qt Creator诊断网络电话问题的终极指南](https://www.contus.com/blog/wp-content/uploads/2021/12/SIP-Protocol-1024x577.png) # 摘要 PJSIP 是一个用于网络电话和VoIP的开源库,它提供了一个全面的SIP协议的实现。本文首先介绍了PJSIP与网络电话的基础知识,并阐述了调试前所需的理论准备,包括PJSIP架构、网络电话故障类型及调试环境搭建。随后,文章深入探讨了在Qt Creator中进行PJSIP调试的实践,涵盖日志分析、调试工具使用以及调试技巧和故障排除。此外,

以客户为导向的离岸团队项目管理与敏捷转型

### 以客户为导向的离岸团队项目管理与敏捷转型 在项目开发过程中,离岸团队与客户团队的有效协作至关重要。从项目启动到进行,再到后期收尾,每个阶段都有其独特的挑战和应对策略。同时,帮助客户团队向敏捷开发转型也是许多项目中的重要任务。 #### 1. 项目启动阶段 在开发的早期阶段,离岸团队应与客户团队密切合作,制定一些指导规则,以促进各方未来的合作。此外,离岸团队还应与客户建立良好的关系,赢得他们的信任。这是一个奠定基础、确定方向和明确责任的过程。 - **确定需求范围**:这是项目启动阶段的首要任务。业务分析师必须与客户的业务人员保持密切沟通。在早期,应分解产品功能,将每个功能点逐层分

C#并发编程:加速变色球游戏数据处理的秘诀

![并发编程](https://img-blog.csdnimg.cn/1508e1234f984fbca8c6220e8f4bd37b.png) # 摘要 本文旨在深入探讨C#并发编程的各个方面,从基础到高级技术,包括线程管理、同步机制、并发集合、原子操作以及异步编程模式等。首先介绍了C#并发编程的基础知识和线程管理的基本概念,然后重点探讨了同步原语和锁机制,例如Monitor类和Mutex与Semaphore的使用。接着,详细分析了并发集合与原子操作,以及它们在并发环境下的线程安全问题和CAS机制的应用。通过变色球游戏案例,本文展示了并发编程在实际游戏数据处理中的应用和优化策略,并讨论了

深度学习 vs 传统机器学习:在滑坡预测中的对比分析

![基于 python 的滑坡地质灾害危险性预测毕业设计机器学习数据分析决策树【源代码+演示视频+数据集】](https://opengraph.githubassets.com/f6155d445d6ffe6cd127396ce65d575dc6c5cf82b0d04da2a835653a6cec1ff4/setulparmar/Landslide-Detection-and-Prediction) 参考资源链接:[Python实现滑坡灾害预测:机器学习数据分析与决策树建模](https://wenku.csdn.net/doc/3bm4x6ivu6?spm=1055.2635.3001.

多项式相关定理的推广与算法研究

### 多项式相关定理的推广与算法研究 #### 1. 定理中 $P_j$ 顺序的优化 在相关定理里,$P_j$ 的顺序是任意的。为了使得到的边界最小,需要找出最优顺序。这个最优顺序是按照 $\sum_{i} \mu_i\alpha_{ij}$ 的值对 $P_j$ 进行排序。 设 $s_j = \sum_{i=1}^{m} \mu_i\alpha_{ij} + \sum_{i=1}^{m} (d_i - \mu_i) \left(\frac{k + 1 - j}{2}\right)$ ,定理表明 $\mu f(\xi) \leq \max_j(s_j)$ 。其中,$\sum_{i}(d_i

嵌入式平台架构与安全:物联网时代的探索

# 嵌入式平台架构与安全:物联网时代的探索 ## 1. 物联网的魅力与挑战 物联网(IoT)的出现,让我们的生活发生了翻天覆地的变化。借助包含所有物联网数据的云平台,我们在驾车途中就能连接家中的冰箱,随心所欲地查看和设置温度。在这个过程中,嵌入式设备以及它们通过互联网云的连接方式发挥着不同的作用。 ### 1.1 物联网架构的基本特征 - **设备的自主功能**:物联网中的设备(事物)具备自主功能,这与我们之前描述的嵌入式系统特性相同。即使不在物联网环境中,这些设备也能正常运行。 - **连接性**:设备在遵循隐私和安全规范的前提下,与同类设备进行通信并共享适当的数据。 - **分析与决策