Избегайте синхронизировался (это) в Java?

ВАЖНО

. Лучший способ предотвратить SQL Injection - использовать подготовленные выражения вместо экранирования , поскольку демонстрирует принятый ответ .

Существуют библиотеки, такие как Aura.Sql и EasyDB , которые позволяют разработчикам легче использовать подготовленные инструкции. Чтобы узнать больше о том, почему подготовленные операторы лучше в останавливать SQL-инъекцию , см. этот mysql_real_escape_string() обход и недавно зафиксированные уязвимости Unicode SQL Injection в WordPress .

Предотвращение впрыска - mysql_real_escape_string ()

У PHP есть специально созданная функция для предотвращения этих атак. Все, что вам нужно сделать, это использовать функцию функции mysql_real_escape_string.

mysql_real_escape_string берет строку, которая будет использоваться в запросе MySQL, и возвращает ту же строку со всеми попытками внедрения SQL безопасно сбежал. В принципе, это заменит эти неприятные кавычки ('), которые пользователь может ввести с помощью заменителя в MySQL, сэкономленная цитата.

ПРИМЕЧАНИЕ: вы должны подключиться к базе данных, чтобы использовать эту функцию!

// Подключение к MySQL

$name_bad = "' OR 1'"; 

$name_bad = mysql_real_escape_string($name_bad);

$query_bad = "SELECT * FROM customers WHERE username = '$name_bad'";
echo "Escaped Bad Injection: 
" . $query_bad . "
"; $name_evil = "'; DELETE FROM customers WHERE 1 or username = '"; $name_evil = mysql_real_escape_string($name_evil); $query_evil = "SELECT * FROM customers WHERE username = '$name_evil'"; echo "Escaped Evil Injection:
" . $query_evil;

Более подробную информацию вы найдете в MySQL - SQL Injection Prevention .

369
задан Community 23 May 2017 в 01:54
поделиться

12 ответов

Я отвечу на каждый вопрос отдельно.

  1. Некоторый злой код может украсть Вашу блокировку (очень популярный этот, также имеет "случайно" различный)

    , я более волнуюсь [приблизительно 117] случайно . То, что это составляет, - то, что это использование this является частью представленного интерфейса Вашего класса и должно быть зарегистрировано. Иногда способность другого кода использовать Вашу блокировку желаема. Это верно для вещей как Collections.synchronizedMap (см. javadoc).

  2. Все синхронизированные методы в том же классе используют ту же самую блокировку, которая уменьшает пропускную способность

    , Это - чрезмерно упрощенные взгляды; просто избавление от synchronized(this) не решит проблему. Надлежащая синхронизация для пропускной способности возьмет более мысль.

  3. Вы (излишне) представляете слишком много информации

    , Это - вариант № 1. Использование synchronized(this) является частью Вашего интерфейса. Если Вы не хотите/нуждаетесь, это представило, не делайте этого.

125
ответ дан Ravindra babu 23 November 2019 в 00:06
поделиться

Я думаю, указывает на один (кто-то еще использующий Вашу блокировку), и два (все методы с помощью той же блокировки напрасно) может произойти в любом довольно крупном приложении. Особенно, когда нет никакой хорошей коммуникации между разработчиками.

Это не брошено в камне, это - главным образом проблема хорошей практики и предотвращения ошибок.

-3
ответ дан Yoni Roit 23 November 2019 в 00:06
поделиться

Это зависит от задачи, которую Вы хотите сделать, но я не использовал бы его. Кроме того, проверьте, не мог ли thread-save-ness, который Вы хотите к accompish, быть сделан, синхронизируются (это) во-первых? Существуют, также некоторые хорошие привязывают API, который мог бы помочь Вам:)

0
ответ дан Ravindra babu 23 November 2019 в 00:06
поделиться

Короткий ответ : необходимо понять различие и сделать выбор в зависимости от кода.

ответ Long : В целом я старался бы избегать , синхронизируются (это) для сокращения конкуренции, но частные блокировки добавляют сложность, о которой необходимо знать. Так используйте правильную синхронизацию для правильного задания. Если Вы не так испытаны с многопоточным программированием, я придерживался бы блокировки экземпляра и читал бы по этой теме. (Который сказал: просто использование синхронизируется (это) автоматически не делает Ваш класс полностью ориентированным на многопотоковое исполнение.) Это не легкая тема, но как только Вы привыкаете к ней, ответ, использовать ли , синхронизируется (это) , или не прибывает естественно.

3
ответ дан tcurdt 23 November 2019 в 00:06
поделиться

Если Вы решили что:

  • вещь, которую необходимо сделать, соединяют текущий объект; и
  • Вы хотите заблокировать его с гранулярностью, меньшей, чем целый метод;

тогда я не вижу табу по synchronizezd (это).

Некоторые люди сознательно используют, синхронизировался (это) (вместо того, чтобы отметить синхронизируемый метод) в целом содержании метода, потому что они думают, что это "более ясно читателю", на котором на самом деле синхронизируется объект. Пока люди делают информированный выбор (например, поймите, что путем выполнения, таким образом, они на самом деле вставляют дополнительные байт-коды в метод и это могло иметь цепную реакцию на потенциальных оптимизациях), я особенно не вижу проблемы с этим. Необходимо всегда документировать параллельное поведение программы, таким образом, я не вижу "'синхронизируемый', публикует поведение" аргумент, как являющийся настолько востребованным.

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

5
ответ дан Neil Coffey 23 November 2019 в 00:06
поделиться

java.util.concurrent пакет значительно уменьшил сложность моего ориентированного на многопотоковое исполнение кода. У меня только есть неподтвержденная информация для продолжения, но большая часть работы, которую я видел с synchronized(x), кажется, повторно реализует Блокировку, Семафор или Фиксатор, но использует мониторы низшего уровня.

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

7
ответ дан jamesh 23 November 2019 в 00:06
поделиться

Там кажется различным согласием в C# и ожиданиях Java это. большинство Java кодирует, я видел использование:

// apply mutex to this instance
synchronized(this) {
    // do work here
}

, тогда как большинство кода C# выбирает возможно более безопасный:

// instance level lock object
private readonly object _syncObj = new object();

...

// apply mutex to private instance level field (a System.Object usually)
lock(_syncObj)
{
    // do work here
}

идиома C#, конечно, более безопасна. Как упомянуто ранее, нет злонамеренный / случайный доступ к блокировке может быть сделан снаружи экземпляра. Код Java имеет этот риск также, , но кажется, что сообщество Java гравитировало со временем к немного менее безопасной, но немного более краткой версии.

Это не предназначено как то, чтобы рыть против Java, просто отражение моего опыта, работающего над обоими языками.

11
ответ дан serg10 23 November 2019 в 00:06
поделиться

В то время как я соглашаюсь о не соблюдении вслепую догматических правил, "блокировка, крадя" сценарий кажутся таким образом эксцентриковыми Вам? Поток мог действительно получить блокировку на Вашем объекте "внешне" (synchronized(theObject) {...}), блокируя другие потоки, ожидающие на синхронизируемых методах экземпляра.

, Если Вы не верите во вредоносный код, полагайте, что этот код мог прибыть от третьих лиц (например, при разработке своего рода сервера приложений).

"случайная" версия кажется менее вероятной, но как они говорят, "сделайте что-то защищенное от дурака, и кто-то изобретет лучшего идиота".

, Таким образом, я соглашаюсь с it-depends-on-what-the-class-does философской школой.

<час>

Редактирование после первых 3 комментариев eljenso:

я никогда не испытывал проблему кражи блокировки, но вот мнимый сценарий:

Скажем, Ваша система является контейнером сервлета, и объект, который мы рассматриваем, ServletContext реализация. getAttribute метод должен быть ориентирован на многопотоковое исполнение, поскольку атрибуты контекста обменяны данными; таким образом, Вы объявляете его как synchronized. Давайте также предположим обеспечение общедоступной услуги хостинга на основе контейнерной реализации.

я - Ваш клиент и развертываю мой "хороший" сервлет на Вашем сайте. Это происходит, что мой код содержит вызов к getAttribute.

хакер А, замаскированный как другой клиент, развертывает свой злонамеренный сервлет на Вашем сайте. Это содержит следующий код в init метод:

synchronized (this.getServletConfig().getServletContext()) {
   while (true) {}
}

Принятие мы совместно используем тот же контекст сервлета (позволенный спецификацией целый, эти два сервлета находятся на том же виртуальном хосте), мой запрос getAttribute заблокирован навсегда. Хакер достиг DoS на моем сервлете.

Это нападение не возможно, если getAttribute синхронизируется на частной блокировке, потому что сторонний код не может получить эту блокировку.

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

, Таким образом, я сделал бы свое проектное решение на основе соображения безопасности: я буду иметь полный контроль над кодом, который имеет доступ к экземплярам? Каково было бы последствие содержания потока блокировка на экземпляре неограниченно долго?

15
ответ дан Olivier 23 November 2019 в 00:06
поделиться

В то время как Вы используете, синхронизировался (это), Вы используете экземпляр класса в качестве самой блокировки. Это означает, что, в то время как блокировка получена поток 1 , , поток 2 должен ожидать.

предположим следующий код:

public void method1() {
    // do something ...
    synchronized(this) {
        a ++;      
    }
    // ................
}


public void method2() {
    // do something ...
    synchronized(this) {
        b ++;      
    }
    // ................
}

Метод 1 изменение переменной и метод 2 изменения переменной b, параллельной модификации той же переменной двумя потоками нужно избежать, и это. НО в то время как thread1, изменяющий и thread2, изменяющий b, это может быть выполнено без любого состояния состязания.

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

решение состоит в том, чтобы использовать 2 различные блокировки для [1 111] два различные переменные:

public class Test {

    private Object lockA = new Object();
    private Object lockB = new Object();

    public void method1() {
        // do something ...
        synchronized(lockA) {
            a ++;      
        }
        // ................
    }


    public void method2() {
        // do something ...
        synchronized(lockB) {
            b ++;      
        }
        // ................
    }

}

вышеупомянутый пример использует более мелкомодульные блокировки (2 блокировки вместо этого одна ( lockA и lockB для переменных и b соответственно) и в результате позволяет лучший параллелизм, с другой стороны, это стало более сложным, чем первый пример...

52
ответ дан informatik01 23 November 2019 в 00:06
поделиться

Ну, во-первых нужно указать что:

public void blah() {
  synchronized (this) {
    // do stuff
  }
}

семантически эквивалентно:

public synchronized void blah() {
  // do stuff
}

, который является одной причиной не использовать synchronized(this). Вы могли бы утверждать, что можно сделать материал вокруг synchronized(this) блок. Обычная причина состоит в том, чтобы не иметь необходимость сделать синхронизируемую проверку вообще, которая приводит ко всем видам проблем параллелизма, конкретно проверенный дважды заблокированная проблема , который просто идет, чтобы показать, насколько трудный это может быть должно осуществить относительно простую ориентированную на многопотоковое исполнение проверку.

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

кроме того, поскольку Вы сослались на, частные блокировки могут управлять гранулярностью. Один набор операций на объекте мог бы быть полностью не связан с другим, но synchronized(this) взаимно исключит доступ ко всем ним.

synchronized(this) просто действительно ничего не дает Вам.

84
ответ дан Mnementh 23 November 2019 в 00:06
поделиться

Нет, Вы не были должны всегда . Однако я склонен избегать его, когда существует несколько опасений на конкретном объекте, который только должен быть ориентирован на многопотоковое исполнение относительно себя. Например, у Вас мог бы быть изменяемый объект данных, который имеет "маркировку" и "родительские" поля; они должны быть ориентированы на многопотоковое исполнение, но изменение одного не должно блокироваться, другой от того, чтобы быть писать/читать. (На практике я избежал бы этого путем объявления энергозависимых полей и/или использования оберток AtomicFoo java.util.concurrent).

Синхронизация в целом немного неуклюжа, поскольку она бросает большую блокировку вместо того, чтобы думать точно, как потокам можно было бы позволить работать друг вокруг друга. Используя synchronized(this) является еще более неуклюжим и антиобщественным, поскольку это говорит, что "никто не может измениться ничто на этом классе, в то время как я держу блокировку". Как часто необходимо на самом деле сделать это?

у меня очень было бы больше детализированных блокировок; даже если Вы действительно хотите мешать всему измениться (возможно, Вы сериализируете объект), можно просто получить все блокировки для достижения того же самого, плюс он является более явным тот путь. Когда Вы используете synchronized(this), не ясно точно, почему Вы синхронизируетесь, или каковы побочные эффекты могли бы быть. Если Вы используете synchronized(labelMonitor), или еще лучше labelLock.getWriteLock().lock(), ясно, что Вы делаете и чем ограничены эффекты Вашего критического раздела.

3
ответ дан Andrzej Doyle 23 November 2019 в 00:06
поделиться

Хороший пример использования synchronized (this).

// add listener
public final synchronized void addListener(IListener l) {listeners.add(l);}
// remove listener
public final synchronized void removeListener(IListener l) {listeners.remove(l);}
// routine that raise events
public void run() {
   // some code here...
   Set ls;
   synchronized(this) {
      ls = listeners.clone();
   }
   for (IListener l : ls) { l.processEvent(event); }
   // some code here...
}

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

Конечно, его можно очень легко переписать с использованием поля synchronized on private. Но иногда, когда у нас уже есть дизайн с синхронизированными методами (то есть унаследованный класс, от которого мы производим, synchronized (это) может быть единственным решением).

0
ответ дан 23 November 2019 в 00:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: