1. 概述

当我们处理多线程项目时,我们知道 如果多个线程共享未考虑线程安全的对象,则线程可能会出现意外行为

我们中的许多人可能都遇到过线程安全问题。那么问题来了,“这个类是线程安全的吗?”经常浮现在脑海中。

Java 应用程序通过 JDBC 访问关系数据库并使用多线程是很常见的。在本快速教程中,我们将讨论 java.sql.Connection 是否是线程安全的。

2. java.sql.Connection 接口

当我们从应用程序通过 JDBC 访问数据库时,我们将直接或间接使用 java.sql.Connection 对象。我们依靠这些连接对象来执行数据库操作。因此, java.sql.Connection 是JDBC中非常重要的类型。

多个线程需要同时与数据库通信也是一种常见的情况。因此,我们经常听到这样的问题:“ java.sql.Connection 是线程安全的吗?”

在接下来的几节中,我们将仔细研究这个问题。此外,我们将讨论在多个线程中使用 java.sql.Connection 对象的正确方法,以便多个线程可以同时访问数据库。

3. 线程安全和 java.sql.Connection

首先,我们快速谈谈线程安全线程安全是一种编程方法。也就是说,它是一个与实现相关的概念。 因此,我们可以使用不同的技术来使实现线程安全——例如,无状态实现、不可变实现等等。

现在,让我们看一下 java.sql.Connection 。首先,它是一个接口——它不包含任何实现。因此, 如果我们一般性地问:“ java.sql.Connection 是线程安全的吗?”,那就没有多大意义了。 我们必须检查实现此接口的类,以确定实现是否是线程安全的。

好吧,我马上想到几个问题:哪些类实现了这个接口?它们是线程安全的吗?

通常,我们不会在应用程序代码中实现 java.sql.Connection 接口。 JDBC驱动程序将实现这个接口, 以便我们可以连接到特定的数据库,例如SQL Server或Oracle。

因此, Connection 实现的线程安全性完全依赖于 JDBC 驱动程序。

接下来,我们将探讨几个数据库 JDBC 驱动程序作为示例。

4. java.sql.Connection 实现示例

Microsoft SQL Server 和 Oracle Database 是两种广泛使用的关系数据库产品。

在本节中,我们将研究这两个数据库的 JDBC 驱动程序,并讨论它们的 java.sql.Connection 接口的实现是否是线程安全的。

4.1.微软SQL服务器

Microsoft SQL Server 驱动程序类 SQLServerConnection 实现了 java.sql.Connection 接口,并且根据其 Javadoc 不是线程安全的:

SQLServerConnection 不是线程安全的,但是从单个连接创建的多个语句可以在并发线程中同时处理。

因此,这意味着 我们不应该在线程之间共享 SQLServerConnection 对象,但我们可以共享从同一个 SQLServerConnection 对象创建的语句

接下来我们来看看另一个知名的数据库产品——Oracle数据库。

4.2.甲骨文数据库

官方Oracle JDBC驱动程序以线程安全的方式实现 java.sql.Connection 接口。

Oracle在其官方文档中声明了其 Connection 实现的线程安全性:

Oracle JDBC 驱动程序为使用 Java 多线程的应用程序提供全面支持并对其进行了高度优化……

然而,Oracle 强烈反对在多个线程之间共享数据库连接。避免允许多个线程同时访问连接......

好了,根据上面的描述,我们可以说Oracle的连接实现是线程安全的。但是, “强烈建议不要”在多个线程之间共享连接对象

因此,从 SQL Server 和 Oracle 示例中,我们知道我们不能假设 java.sql.Connection 实现是线程安全的。那么,我们可能会问,如果我们想要多个线程同时访问数据库,正确的做法是什么?让我们在下一节中弄清楚它。

5. 使用连接池

当我们从应用程序访问数据库时,我们首先需要建立与数据库的连接。这被认为是一项昂贵的操作。为了提高性能,通常我们会使用连接池

让我们快速了解一下连接池在多线程场景下是如何工作的。

一个连接池保存多个连接对象。我们可以配置池的大小。

当多个线程需要并发访问数据库时,它们会向连接池请求连接对象。

如果池中还有空闲连接,线程将获取连接对象并开始其数据库操作。线程完成工作后,会将连接返回到池中。

如果池中没有空闲连接,该线程将等待另一个线程将连接对象返回到池中。

因此, 连接池允许多个线程使用不同的连接对象同时访问数据库,而不是共享同一个连接对象

进一步,这样我们就不用关心 Connection 接口的实现是否是线程安全的。

六,结论

在本文中,我们讨论了常见问题: java.sql.Connection 线程安全吗?

由于 java.sql.Connection 是一个接口,因此很难预测其实现是否是线程安全的。

此外,我们还指出,如果多个线程需要同时访问数据库,则连接池是处理连接的正确方法。