Когда ключевое слово Java Language используется для изменения метода или кодового блока, оно может убедиться, что в максимум максимум один поток выполняет код одновременно.
1. Когда два параллельных потока получают доступ к этому синхронизированному (этому) синхронизированному кодовому блоку в одном объекте объекта, в течение одного времени можно выполнить только один поток. Другой поток должен ждать, пока текущий поток выполнит этот кодовый блок, прежде чем он сможет выполнить кодовый блок.
2. Однако, когда один поток обращается к синхронизированному (этой) кодовому блоку синхронизации объекта, другой поток все еще может получить доступ к несинхронизированному (это) блоку кода синхронизации в этом объекте.
3. Особенно важно, чтобы, когда поток обращается к синхронизированному (это) блоку синхронизации объекта, другие потоки будут блокировать доступ ко всем другим блокам синхронизированной (этой) синхронизации в объекте.
4. Третий пример также относится к другим блокам синхронного кода. То есть, когда поток обращается к синхронизированному (этой) кодовому блоку синхронизации объекта, он получает блокировку объекта этого объекта. В результате другие потоки доступа ко всем частям синхронного кода объекта объекта временно заблокированы.
5. Приведенные выше правила также применяются к другим блокировкам объектов.
Приведите пример:
1. Когда два параллельных потока получают доступ к этому синхронизированному (этому) синхронизированному кодовому блоку в одном объекте объекта, в течение одного времени можно выполнить только один поток. Другой поток должен ждать, пока текущий поток выполнит этот кодовый блок, прежде чем он сможет выполнить кодовый блок.
пакет ths; public class thread1 реализует runnable {public void run () {synchronized (this) {for (int i = 0; i <5; i ++) {System.out.println (thread.currentThread (). getName () + "Синхронизированный цикл" + i); }}} public static void main (string [] args) {thread1 t1 = new Thread1 (); Thread TA = новый поток (T1, "A"); Thread TB = новый поток (T1, "B"); ta.start (); TB.Start (); }}результат:
Синхронизированный цикл 0
Синхронизированный петля 1
Синхронизированный петля 2
Синхронизированный цикл 3
Синхронизированный цикл 4
B Синхронизированный петля 0
B Синхронизированный петля 1
B Синхронизированный петля 2
B Синхронизированный цикл 3
B Синхронизированный цикл 4
2. Однако, когда один поток обращается к синхронизированному (этой) кодовому блоку синхронизации объекта, другой поток все еще может получить доступ к несинхронизированному (это) блоку кода синхронизации в этом объекте.
пакет ths; public class thread2 {public void m4t1 () {synchronized (this) {int i = 5; while (i-> 0) {System.out.println (think.currentThread (). getName () + ":" + i); try {thread.sleep (500); } catch (прерывание Exception IE) {}}}} public void m4t2 () {int i = 5; while (i-> 0) {System.out.println (think.currentThread (). getName () + ":" + i); try {thread.sleep (500); } catch (прерывание Exception IE) {}}} public static void main (string [] args) {final thread2 myT2 = new Thread2 (); Поток t1 = new Thread (new Runnable () {public void run () {myt2.m4t1 ();}}, "t1"); Поток t2 = new Thread (new Runnable () {public void run () {myt2.m4t2 ();}}, "t2"); t1.start (); t2.start (); }} результат:
T1: 4
T2: 4
T1: 3
T2: 3
T1: 2
T2: 2
T1: 1
T2: 1
T1: 0
T2: 0
3. Особенно важно, чтобы, когда поток обращается к синхронизированному (это) блоку синхронизации объекта, другие потоки будут блокировать доступ ко всем другим блокам синхронизированной (этой) синхронизации в объекте.
// Модифицировать Thread2.m4t2 () Метод: public void m4t2 () {synchronized (this) {int i = 5; while (i-> 0) {System.out.println (think.currentThread (). getName () + ":" + i); try {thread.sleep (500); } catch (прерванное искусство т.е.) {}}}}результат:
T1: 4
T1: 3
T1: 2
T1: 1
T1: 0
T2: 4
T2: 3
T2: 2
T2: 1
T2: 0
4. Третий пример также относится к другим блокам синхронного кода. То есть, когда поток обращается к синхронизированному (этой) кодовому блоку синхронизации объекта, он получает блокировку объекта этого объекта. В результате другие потоки доступа ко всем частям синхронного кода объекта объекта временно заблокированы.
// Измените метод Thread2.m4t2 () следующим образом: public Synchrinized void m4t2 () {int i = 5; while (i-> 0) {System.out.println (think.currentThread (). getName () + ":" + i); try {thread.sleep (500); } catch (прерванное искусство т.е.) {}}} результат:
T1: 4
T1: 3
T1: 2
T1: 1
T1: 0
T2: 4
T2: 3
T2: 2
T2: 1
T2: 0
5. Приведенные выше правила также применяются к другим блокировкам объектов:
пакет ths; public class thread3 {class inner {private void m4t1 () {int i = 5; while (i-> 0) {System.out.println (think.currentThread (). getName () + ": inner.m4t1 () =" + i); try {thread.sleep (500); } catch (прерывание Exception IE) {}}} private void m4t2 () {int i = 5; while (i-> 0) {System.out.println (think.currentThread (). getName () + ": inner.m4t2 () =" + i); try {thread.sleep (500); } catch (прерывание Exception IE) {}}}} private void m4t1 (inner inner) {synchronized (inner) {// Использовать блокировку объекта inner.m4t1 (); } private void m4t2 (внутренний внутренний) {inner.m4t2 (); } public static void main (string [] args) {final thread3 myT3 = new Thread3 (); final inner inner = myt3.new inner (); Поток T1 = новый поток (new Runnable () {public void run () {myt3.m4t1 (inner);}}, "t1"); Поток t2 = new Thread (new Runnable () {public void run () {myt3.m4t2 (inner);}}, "t2"); t1.start (); t2.start (); }}результат:
Хотя поток T1 получает блокировку объекта на внутренней части, поскольку потока T2 обращается к асинхронной части в том же внутреннем. Следовательно, два потока не мешают друг другу.
T1: inner.m4t1 () = 4
T2: inner.m4t2 () = 4
T1: inner.m4t1 () = 3
T2: inner.m4t2 () = 3
T1: inner.m4t1 () = 2
T2: inner.m4t2 () = 2
T1: inner.m4t1 () = 1
T2: inner.m4t2 () = 1
T1: inner.m4t1 () = 0
T2: inner.m4t2 () = 0
Теперь поставьте синхронизированный перед Inner.m4t2 ():
Частный синхронизированный void m4t2 () {int i = 5; while (i-> 0) {System.out.println (think.currentThread (). getName () + ": inner.m4t2 () =" + i); try {thread.sleep (500); } catch (прерванное искусство т.е.) {}}}результат:
Хотя потоки T1 и T2 обращаются к двум неродственным частям одного и того же внутреннего объекта, поскольку T1 сначала получает блокировку объекта во внутреннюю часть, доступ T2 к inner.m4t2 () также блокируется, поскольку m4t2 () является методом синхронизации во внутреннем.
T1: inner.m4t1 () = 4
T1: inner.m4t1 () = 3
T1: inner.m4t1 () = 2
T1: inner.m4t1 () = 1
T1: inner.m4t1 () = 0
T2: inner.m4t2 () = 4
T2: inner.m4t2 () = 3
T2: inner.m4t2 () = 2
T2: inner.m4t2 () = 1
T2: inner.m4t2 () = 0
Статья 2:
Синхронизированное ключевое слово, которое включает в себя два использования: синхронизированный метод и синхронизированный блок.
1. Синхронизированный метод: объявить синхронизированный метод, добавив синхронизированное ключевое слово в объявление метода. нравиться:
общественный синхронизированный void accessval (int newval);
Синхронизированный метод управляет доступом к переменным элемента класса: каждый экземпляр класса соответствует блокировке, и каждый синхронизированный метод должен получить блокировку экземпляра класса, который вызывает метод, прежде чем его можно будет выполнить. В противном случае, нить, к которой он принадлежит, заблокирована. Как только метод будет выполнен, он будет занимать исключительно замок. Замок не будет выпущен, пока не вернется из метода. Заблокированный поток может получить блокировку и повторно ввести исполняемое состояние. Этот механизм гарантирует, что в то же время, для каждого экземпляра класса, в большинстве случаев одну из всех функций -членов, объявленных синхронизированными, находится в исполняемом состоянии (поскольку в большинстве случаев можно получить блокировку, соответствующую экземпляру класса), что эффективно избегает конфликтов доступа переменных членов класса (до тех пор, пока все возможные методы доступа к классу объявляют синхронизируемые).
В Java, не только экземплярах класса, но и каждый класс также соответствует блокировке, поэтому мы можем объявить статическую функцию элемента класса как синхронизированный для управления его доступом к статическим переменным элемента класса.
Недостаток синхронизированного метода: объявление большого метода как синхронизированный, значительно повлияет на эффективность. Как правило, если метод класса потока run () объявляется синхронизированным, поскольку он работает на протяжении всего срока службы потока, он приведет к тому, что он никогда не будет успешным ни в каком синхронизированном методе этого класса. Конечно, мы можем решить эту проблему, поместив код, который обращается к переменным члена класса в специальный метод, объявляя его синхронизированным, и вызывая его в основном методе, но Java предоставляет нам лучшее решение, то есть синхронизированный блок.
2. Синхронизированный блок: объявить синхронизированный блок через синхронизированное ключевое слово. Синтаксис выглядит следующим образом:
Synchronized (Syncobject) {// код, который позволяет управлять доступом} Синхронизированный блок - это кодовый блок, в котором код должен получить блокировку синкобата объекта (как упоминалось ранее, это может быть экземпляр класса или класс), прежде чем его можно будет выполнить. Конкретный механизм такой же, как описано выше. Поскольку он может быть нацелен на любой кодовый блок, и заблокированные объекты могут быть указаны в любое время, он более гибкий.
Некоторые понимания синхронизированного (это) <br /> 1. Когда два параллельных потока получают доступ к этому синхронизированному (этому) синхронизированному кодовому блоку в одном и том же объекте, в течение одного времени можно выполнить только один поток. Другой поток должен ждать, пока текущий поток выполнит этот кодовый блок, прежде чем он сможет выполнить кодовый блок.
2. Однако, когда один поток обращается к синхронизированному (этой) кодовому блоку синхронизации объекта, другой поток все еще может получить доступ к несинхронизированному (это) блоку кода синхронизации в этом объекте.
3. Особенно важно, чтобы, когда поток обращается к синхронизированному (это) блоку синхронизации объекта, другие потоки будут блокировать доступ ко всем другим блокам синхронизированной (этой) синхронизации в объекте.
4. Третий пример также относится к другим блокам синхронного кода. То есть, когда поток обращается к синхронизированному (этой) кодовому блоку синхронизации объекта, он получает блокировку объекта этого объекта. В результате другие потоки доступа ко всем частям синхронного кода объекта объекта временно заблокированы.
5. Приведенные выше правила также применяются к другим блокировкам объектов.
Как использовать синхронизированный на Java
Например: объект похож на большой дом, дверь всегда открыта. В доме много комнат (то есть метод).
Эти комнаты заблокированы (синхронизированный метод) и не заблокированы (нормальный метод). У двери есть ключ, который может открыть все запертые комнаты.
Кроме того, я сравниваю все темы, которые хотят вызвать метод объекта с людьми, которые хотят ввести комнату в этом доме. Есть только так много вещей, давайте посмотрим, как работают эти вещи.
Здесь мы сначала уточняем наши предпосылки. У объекта есть по крайней мере один синхронизированный метод, в противном случае, какой смысл этого ключа? Конечно, для нас не будет такой темы.
Человек хотел войти в запертую комнату. Он подошел к двери дома и увидел там ключ (это означает, что никто еще не хочет использовать запертую комнату). Поэтому он подошел, получил ключи и использовал комнаты, как он планировал. Имейте в виду, что он возвращает ключ сразу после использования запертой комнаты каждый раз. Даже если он хочет использовать две запертые комнаты подряд, он вернет ключи, чтобы получить их. Следовательно, принцип использования ключа в обычных случаях: «Займитесь по мере использования, и вернуть его, как только вы его используете».
В настоящее время другие люди могут использовать эти разблокированные комнаты без ограничений. Один человек может использовать одну комнату, и два человека могут использовать одну комнату, без ограничений. Но если кто -то хочет войти в запертую комнату, он должен бежать к воротам, чтобы посмотреть. Конечно, если у вас есть ключ, вы уйдете. Если у вас его нет, вы можете только ждать. Если многие люди ждут этого ключа, кто получит ключ первым после его возвращения? Не гарантируется. Как и парень в предыдущем примере, который хотел использовать две запертые комнаты подряд, если бы были другие люди, ожидающие ключей в середине, не было никакой гарантии, что этот парень получит его снова. (Спецификация Java четко гласит, что во многих местах не гарантируется, что, например, сколько времени требуется для Thread.sleep () Чтобы вернуться к бегу после отдыха, в первую очередь выполняется тем же приоритет, и какой поток в пуле ожидания будет дана приоритет после того, как блокировка будет выпущена и т. Д. Я думаю, что окончательное решение приходит в JVM. Причина, по которой не является тем, что это не так, когда это не является решением. Состояние, но на основе многих статей.
Поскольку существует слишком много условий суждения, если вы это говорите, это может повлиять на продвижение Java, или это может быть связано с защитой интеллектуальной собственности. Солнце дало мне обещание и прошел через это. В этом нет ничего плохого. Но я считаю, что эти неопределенности не совсем неопределенны. Потому что сам компьютер работает в соответствии с инструкциями. Даже если явление кажется случайным, оно на самом деле регулярно. Любой, кто изучал компьютеры, знает, что научное название случайных чисел на компьютерах-это псевдолупольные числа, которые написаны людьми, использующими определенные методы, и они просто выглядят случайными. Кроме того, возможно, это потому, что слишком сложно убедиться и не очень значимо, поэтому, если вы не уверены, вы не уверены. )
Давайте посмотрим на блок кода синхронизации. Существует небольшая разница от метода синхронизации.
1. С точки зрения размера, блок кода синхронизации меньше, чем метод синхронизации. Вы можете думать о блоке кода синхронизации как пространство в разблокированной комнате, разделенной заблокированным экраном.
2. Блок кода синхронизации также может искусственно указать ключ получения определенного другого объекта. Точно так же, как указать, какой ключ для разблокировки экрана, вы можете использовать ключ в этой комнате; Вы также можете указать, что ключ другого дома может открыть его. Таким образом, вам нужно бежать в другой дом, чтобы принести этот ключ и использовать ключ этого дома, чтобы открыть запертый экран этого дома.
Помните, что ключ к тому другому дому, который вы получили, не влияет на других людей, входящих в комнату без замков в этом доме.
Зачем использовать синхронные кодовые блоки? Я думаю, что это должно быть похоже на это: во -первых, часть синхронизации программы оказывает большое влияние на эффективность работы, и сначала метод, как правило, для создания некоторых локальных переменных, а затем выполнить некоторые операции на этих переменных, таких как операции, отображение и т. Д.; и чем больше кода, покрываемого синхронизацией, тем серьезнее влияние на эффективность. Поэтому мы обычно пытаемся сузить его влияние.
Как это сделать? Синхронизировать кодовые блоки. Мы только синхронизируем места синхронизации в одном методе, таких как операции.
Кроме того, функция синхронных кодовых блоков, которые могут указать Keys, имеет дополнительное преимущество, которое состоит в том, что он может занимать ключи объекта в течение определенного периода времени. Вы помните принципы использования ключей в обычных ситуациях, упомянутых ранее? Теперь это не обычная ситуация. Ключ, который вы получили, никогда не возвращается, но возвращается только при выходе из блока синхронного кода.
Я также использовал парня впереди, который хотел использовать две запертые комнаты подряд, чтобы сделать пример. Как я могу продолжать использовать еще один после его использования? Используйте синхронные кодовые блоки. Сначала создайте еще один поток, сделайте блок синхронного кода и укажите блокировку этого блока кода на ключ дома. Затем запустите эту ветку. Пока вы можете взять ключ к дому при входе в этот кодовый блок, вы можете сохранить его, пока не выйдете из этого блока кода. Другими словами, вы можете даже пересечь все запертые комнаты в этой комнате или даже спать (10*60*1000), и у двери все еще есть 1000 потоков. Очень приятно.
Здесь мы поговорим о корреляции между методом Sleep () и ключом. Если поток вынужден спать () после получения ключа и не завершил синхронное содержание, ключ все еще там. Ключ не будет возвращен, пока он не запустится снова и не завершит все синхронное содержание. Помните, что этот парень просто устал работать, поэтому он пошел, чтобы сделать перерыв, и он не закончил то, что собирался сделать. Чтобы избежать входа в комнату и впадать в беспорядок, он должен носить единственный ключ на своем теле, даже когда он спит.
Наконец, некоторые люди могут спросить, зачем вам открыть ключ, а не ключ и дверь? Я думаю, что это исключительно из -за сложности. Конечно, один ключ и одна дверь безопаснее, но это будет связано с множеством проблем. Поколение, хранение, приобретение, возврат и т. Д. Ключи. Его сложность может увеличиваться в геометрических последовательностях с увеличением метода синхронизации, что серьезно влияет на эффективность. Это также компромисс. Насколько нежелательно немного повысить безопасность, что приводит к значительному снижению эффективности.
Простой пример синхронизации
public Class TextThread {public static void main (string [] args) {txtthread tt = new txtthread (); новый поток (tt) .start (); новый поток (tt) .start (); новый поток (tt) .start (); новый поток (tt) .start (); }} класс txtthread реализует runnable {int num = 100; String str = new string (); public void run () {synchronized (str) {while (num> 0) {try {thread.sleep (1); } catch (Exception e) {e.getMessage (); } System.out.println (think.currentThread (). GetName () + "Это" + num-); }}}}В приведенном выше примере, чтобы создать разницу во времени, то есть возможность донести ошибку, используется Thread.sleep (10).
Механизм поддержки и синхронизации Java для многопоточного чтения очень популярен. Похоже, что использование синхронизированного ключевого слова может легко решить проблему синхронизации многопоточных общих данных. Что именно? Также необходимо иметь глубокое понимание роли синхронизированных ключевых слов, прежде чем вы сможете сделать вывод.
В целом, синхронизированное ключевое слово может использоваться в качестве модификатора функции или в качестве оператора в функции, которая представляет собой метод синхронизации и блок операторов синхронизации, которые обычно упоминаются. Если вы классифицируете его более тщательно, синхронизированный может действовать по переменным экземплярам, ссылкам на объекты, статических функциях и классовых литералов (название класса буквальные константы).
Прежде чем мы уточнем дальше, нам нужно уточнить несколько моментов:
О. Является ли синхронизированное ключевое слово, добавляется в метод или объект, приобретает он заблокирован, а не рассматривает кусок кода или функции как блокировку, и метод синхронизации, вероятно, будет еще более вероятным
Объект доступа к его ветке.
Б. Каждый объект имеет только один замок, связанный с ним.
C. Реализация синхронизации требует большого количества системных накладных расходов в качестве затрат и может даже вызвать тупики, поэтому старайтесь избегать ненужного контроля синхронизации.
Далее, давайте обсудим влияние синхронизации с использованием различных мест на коде:
Предполагая, что P1 и P2 являются разными объектами одного и того же класса, этот класс определяет блоки синхронизации или методы синхронизации в следующих ситуациях, а P1 и P2 могут их вызывать.
1. Когда синхронизированный используется в качестве модификатора функции, пример кода заключается в следующем:
Public Synchronized void methodaaaaa () {//….}Это метод синхронизации. Итак, какой объект синхронизирован заблокирован в настоящее время? То, что он блокирует, - это назвать этот объект синхронного метода. То есть, когда объект P1 выполняет этот метод синхронизации в разных потоках, между ними будет сформировано взаимное исключение для достижения влияния синхронизации. Однако другой объект P2, сгенерированный классом, к которому принадлежит этот объект, может произвольно вызвать этот метод с добавлением синхронизированного ключевого слова.
Приведенный выше пример код эквивалентен следующему коду:
public void methodaaa () {синхронизированный (this) // (1) {//… ..}}(1) Что это значит в точке? Это относится к объекту, который вызывает этот метод, такой как P1. Можно видеть, что метод синхронизации по существу предназначен для применения синхронизации к ссылке на объект. Только поток, который получил блокировку объекта P1, может вызвать метод синхронизации P1. Для P2 блокировка P1 не имеет к этому никакого отношения. Программа может также избавиться от контроля механизма синхронизации в этой ситуации, вызывая путаницу данных: (
2. Синхронизировать блоки, пример кода заключается в следующем:
public void Method3 (someObject so) {synchronized (so) {//… ..}}В настоящее время замок является объектом SO. Тот, кто получает блокировку, может запустить код, который он управляет. Когда есть четкий объект в качестве блокировки, вы можете написать программу, как эта, но когда нет четкого объекта в качестве блокировки и просто хотите синхронизировать кусок кода, вы можете создать переменную специального экземпляра (это должно быть объектом), чтобы действовать как блокировка:
Класс Foo реализует runnable {private byte [] lock = new Byte [0]; // Специальная переменная экземпляра public void methoda () {synchronized (lock) {//…}} //… ..}ПРИМЕЧАНИЕ. Объекты массива нулевой длины более экономичны, чем любой объект для создания скомпилированного байтового кода: требуется только 3 Opcodes для генерации объекта байта нулевой длины [], в то время как объект Lock = new Object () требует 7 Opcodes.
3. Используйте синхронизированный к статической функции, пример кода заключается в следующем:
Класс foo {public synchronized static void methodaaaa () // Синхронизированная статическая функция {//…. } public void methodbbb () {synchronized (foo.class) // Literal (Literal Countration Class Literal)}}}}Метод MethodBbb () в коде использует буквальный класс в качестве блокировки. Он имеет тот же эффект, что и синхронизированная статическая функция. Полученная блокировка очень особенная. Это класс, к которому принадлежит объект, который в настоящее время вызывает этот метод (класс, а не конкретный объект, сгенерированный этим классом).
Я помню, что в книге «Эффективная java» я увидел, что использование Foo.class и P1.getClass () в качестве синхронных замков различено, и P1.getClass () не может быть использован для достижения цели блокировки этого класса. P1 относится к объекту, генерируемому классом Foo.
Можно сделать вывод, что если класс определяет синхронизированную статическую функцию A и синхронизированную функцию экземпляра B, то один и тот же объект OBJ в этом классе не будет представлять собой синхронизацию при доступе к двум методам A и B в нескольких потоках, потому что их замки различны. Замок метода a является объектом obj, в то время как блокировка B является классом, к которому принадлежит OBJ.
Резюме следующее:
Выяснить, какие объектные синхронизированные замки могут помочь нам разработать более безопасные многопоточные программы. Есть также несколько советов, чтобы сделать синхронный доступ к общим ресурсам более безопасным:
1. Определите переменную экземпляра Private + ITS METHET, а не переменную экземпляра общественного/защищенного. Если переменная определяется как публичная, объект может обойти контроль метода синхронизации и напрямую получить ее и изменить. Это также один из стандартных методов реализации Javabean.
2. Если переменная экземпляра является объектом, таким как массив или массив, то приведенный выше метод все еще небезопасен, потому что, когда внешний объект получает ссылку на объект экземпляра через метод GET и указывает на другой объект, то частная переменная изменится, что не очень опасно. В настоящее время вам необходимо добавить синхронизированный в метод GET и только вернуть клон () этого частного объекта, чтобы вызывающий абонент получил ссылку на копию объекта
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.