众所周知,AWS lambda可能会重用早期创建的处理程序对象,它确实做到了这一点(参见常见问题解答):
问:AWS Lambda 是否会重用函数实例?
为了提高性能,AWS Lambda可能会选择保留您的函数实例并重用它来服务后续请求,而不是创建新副本。您的代码不应假设这种情况总是会发生。
问题是关于Java
并发。如果我有一个处理程序的类,比如:
public class MyHandler {
private Foo foo;
public void handler(Map<String,String> request, Context context) {
...
}
}
那么,在这里访问和使用对象变量foo
是否是线程安全的?
换句话说:AWS lambda可以同时使用同一个对象进行不同的调用吗?
EDIT我的函数在基于事件的源上处理,特别是它由API Gateway方法调用。
EDIT-2当您想要实现某种到外部资源的连接池时,就会出现这样的问题,所以我想将到外部资源上的连接作为一个对象变量。它实际上按预期工作,但我担心并发问题。
更具体地说,我想知道:AWS lambda的处理程序实例是否可以共享公共堆(内存)?我必须指定这个额外的细节,以防止回答中列出关于java线程安全对象的显而易见和众所周知的事情。
据我所知,Lambda没有并发问题。只有一个调用“拥有”该容器。第二次调用将获得另一个容器(或者可能必须等到第一个容器空闲)。
但是我没有找到任何保证Java内存可见性问题不会发生的方法。在这种情况下,第一次调用所做的更改对于第二次调用来说是不可见的。或者第一次调用的更改将在第二次调用完成更改后写入RAM。
在大多数情况下,可见性问题的处理方式与并发问题相同。因此,我建议开发线程安全(或同步)的Lambda函数。至少只要AWS不会保证我们,他们会在每次调用后做一些事情将CPU状态刷新到内存中。
在使用AWS Lambda时,利用执行上下文重用绝对是一种实践(参见AWS Lambda最佳实践)。但是这并不适用于并发执行,因为对于并发执行,创建了新的容器,因此创建了新的上下文。简而言之,对于并发执行,如果一个处理程序更改了值,另一个不会获得新值。
AWS lambda可以在不同的调用中同时使用相同的对象吗?
AWS lambda的处理程序实例是否可以共享公共堆(内存)?
一个强而明确的NO。AWS Lambda的处理程序实例甚至不能共享文件(在/tmp
中)。
AWS Lambda 容器不能重用于两个或多个并发存在的 Lambda 函数调用,因为这会破坏隔离要求:
问:AWS Lambda 如何隔离我的代码?
每个 AWS Lambda 函数都在自己的隔离环境中运行,并具有自己的资源和文件系统视图。
关于Lambda函数如何工作的官方描述中的“AWS Lambda如何运行我的代码?容器模型”一节指出:
在Lambda函数执行后,AWS Lambda会在一段时间内维护容器,以期待下一次Lambda函数调用。实际上,如果AWS Lambda选择在Lambda函数再次被调用时重用容器,则服务在Lambda函数完成后冻结容器,并解冻容器以供重用。这种容器重用方法具有以下含义:
>
Lambda 函数代码中的任何声明都将保持初始化状态,从而在再次调用函数时提供额外的优化。例如,如果您的 Lambda 函数建立数据库连接,则在后续调用中使用原始连接,而不是重新建立连接。可以在代码中添加逻辑,以便在创建连接之前检查连接是否已存在。
每个容器都在/tmp目录中提供一些磁盘空间。当容器被冻结时,目录内容仍然存在,提供了可用于多次调用的临时缓存。您可以添加额外的代码来检查缓存中是否有您存储的数据。
如果AWS Lambda选择重用容器,则由Lambda函数启动但在函数结束时未完成的后台进程或回调将恢复。您应该确保代码中的任何后台进程或回调(如果Node.js)在代码退出之前都已完成。
正如您所看到的,当试图利用容器重用时,Lambda函数的多个并发调用之间绝对没有关于竞争条件的警告。唯一的字条是“不要依赖它!”。
问题内容: 本文在这里建议使用“为了使与并发GC并行年轻一代的GC”。 我的困惑是,为了同时启用并行和并发GC,我应该 使用或 同时使用 和 ? 聚苯乙烯 我正在使用JVM 6。 问题答案: 由于链接的文档是针对1.4.2 VM的,因此我假设您正在使用(JVM 5和6的行为有所不同)。 从http://java.sun.com/docs/hotspot/gc1.4.2/ 如果在命令行上使用了-XX
主要内容:实例对象可以返回由线程完成的计算结果,而接口只能运行线程。 对象返回对象,该对象提供监视线程执行的任务进度的方法。 对象可用于检查的状态,然后线程完成后从中检索结果。 它还提供超时功能。 语法 实例 以下程序显示了基于线程的环境中和的使用。 这将产生以下结果。
Java 是最先支持多线程开发的语言之一, Java 多线程和并发也是 Java 学习的重点加难点。本教程根据作者多年 Java 开发经验总结而成,旨在帮助读者明白并发的原理。
问题内容: 我试图弄清楚如何在Java 8并行流中复制ThreadLocal值。 因此,如果我们考虑到这一点: 哪个输出 有没有办法将ThreadLocal从main()方法克隆到为每次并行执行生成的线程中? 这样,我的结果是: 而不是第一个? 问题答案: 正如Louis在评论中所述,您的示例可以简化为捕获lambda表达式中的局部变量的值 从您的示例中看不出完整的用例是什么。 如果您确切知道将从
问题内容: 我有一个经典的问题,线程将事件推送到第二个线程的传入队列。仅这次,我对性能非常感兴趣。我要实现的是: 我想要并发访问队列,生产者推送,接收者弹出。 当队列为空时,我希望消费者阻止队列,等待生产者。 我的第一个想法是使用,但是我很快意识到它不是并发的,并且会降低性能。另一方面,我现在使用,但仍要为每个出版物支付/ 的费用。由于使用者在找到空队列时不会阻塞,因此我必须进行同步并处于锁定状态
欢迎阅读我的Java8并发教程的第二部分。这份指南将会以简单易懂的代码示例来教给你如何在Java8中进行并发编程。这是一系列教程中的第二部分。在接下来的15分钟,你将会学会如何通过同步关键字,锁和信号量来同步访问共享可变变量。 这篇文章中展示的中心概念也适用于Java的旧版本,然而代码示例适用于Java 8,并严重依赖于lambda表达式和新的并发特性。如果你还不熟悉lambda,我推荐你先阅读我