Перейти к основному содержимому

Является ли java.sql.Connection потокобезопасным?

· 4 мин. чтения

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. Microsoft SQL-сервер

Класс драйвера Microsoft SQL Server, SQLServerConnection , реализует интерфейс java.sql.Connection и не является потокобезопасным, согласно его Javadoc:

  > `SQLServerConnection`  не является потокобезопасным, однако несколько инструкций, созданных из одного соединения, могут обрабатываться одновременно в параллельных потоках.

Таким образом, это означает, что мы не должны совместно использовать объект SQLServerConnection между потоками, но мы можем совместно использовать операторы, созданные из одного и того же объекта SQLServerConnection .

Далее давайте взглянем на другой известный продукт баз данных, Oracle Database.

4.2. База данных Oracle

Официальный драйвер Oracle JDBC реализует интерфейс java.sql.Connection потокобезопасным способом.

Oracle заявляет о безопасности потоков своей реализации Connection в своем официальном документе :

Драйверы Oracle JDBC обеспечивают полную поддержку и оптимизированы для приложений, использующих многопоточность Java… Однако Oracle настоятельно не рекомендует совместное использование соединения с базой данных несколькими потоками. Избегайте одновременного доступа нескольких потоков к соединению...

Что ж, основываясь на приведенном выше описании, мы можем сказать, что реализация соединения Oracle является потокобезопасной. Однако совместное использование объекта соединения несколькими потоками «настоятельно не рекомендуется» .

Итак, из примеров SQL Server и Oracle мы знаем, что нельзя предполагать, что реализация java.sql.Connection является потокобезопасной. Затем мы можем спросить, каков правильный подход, если мы хотим, чтобы несколько потоков одновременно обращались к базе данных? Разберемся в следующем разделе.

5. Использование пула соединений

Когда мы обращаемся к базе данных из нашего приложения, нам нужно сначала установить соединение с базой данных. Это считается дорогостоящей операцией. Для повышения производительности обычно используется пул соединений .

Давайте быстро разберемся, как работает пул соединений в многопоточном сценарии.

Пул соединений содержит несколько объектов соединений. Мы можем настроить размер пула.

Когда нескольким потокам требуется одновременный доступ к базе данных, они запрашивают объекты соединения из пула соединений.

Если в пуле еще есть свободные соединения, поток получит объект соединения и начнет свои операции с базой данных. После того, как поток завершит свою работу, он вернет соединение в пул.

Если в пуле нет свободного соединения, поток будет ждать, пока объект соединения будет возвращен в пул другим потоком.

Таким образом, пул соединений позволяет нескольким потокам одновременно обращаться к базе данных, используя разные объекты соединения, вместо того, чтобы совместно использовать один и тот же объект .

Далее, таким образом, нам не нужно заботиться о том, является ли реализация интерфейса Connection потокобезопасной.

6. Заключение

В этой статье мы обсудили часто задаваемый вопрос: является ли java.sql.Connection потокобезопасным?

Поскольку java.sql.Connection является интерфейсом, непросто предсказать, являются ли его реализации потокобезопасными.

Более того, мы решили, что пул соединений — это правильный способ обработки соединений, если нескольким потокам требуется одновременный доступ к базе данных.