В этой статье описывается разница между синхронизированной (блокировкой объекта) и статическим синхронизированным (блокировка класса) в Java. Поделитесь этим для вашей ссылки, следующим образом:
Разница между синхронизированным и статическим синхронизированным
Анализируя анализ этих двух использований, мы можем понять концепцию блокировки в Java. Одним из них является блокировка экземпляра (заблокирован на объекте экземпляра. Если класс является синглтоном, то блокировка также имеет концепцию глобального блокировки), а другой - глобальный блокировка (блокировка нацелена на класс. Независимо от того, сколько объектов это экземпляр, потоки разделяют блокировку). Замок экземпляра соответствует синхронизированному ключевому слову, в то время как блокировка класса (Global Lock) соответствует статическому синхронизированному (или заблокированному в классе или объекте класса загрузчика класса).
Следующая статья дает хорошее резюме:
1. Разница между синхронизированным и статическим синхронизированным
Синхронизированный блокирует текущий экземпляр (текущий объект) класса, чтобы предотвратить доступ к другим потокам со всеми синхронизированными блоками экземпляра класса одновременно. Обратите внимание, что это «текущий экземпляр класса». Такого нет такого ограничения на два разных экземпляра класса.
Затем статический синхронизированный контролирует одновременный доступ всех экземпляров класса, а статический синхронизированный ограничивает все экземпляры класса в многопользовании для доступа к блоку кода, соответствующего классу в JVM одновременно. Фактически, если в классе синхронизируется метод или кодовый блок, после создания экземпляра класса, экземпляр также будет иметь блок мониторинга, чтобы предотвратить одновременный доступ потоков одновременно синхронизированный блок защиты экземпляра. Статический синхронизирован - это блок мониторинга, общий для всех случаев класса. Это разница между ними. Другими словами, синхронизированный эквивалентен этому. Синхронизированный, в то время как статический синхронизированный эквивалентен чем -то. Синхронизировано. (Адресован позже)
Японский автор, «Джава -картинка с многопоточным дизайном» Цзе Ченгао, имеет такую колонку, как это:
Pulbic Class Something () {public synchronized void issynca () {} public synchronized void issyncb () {} public static synchronized void csynca () {} public static synchronized void csyncb () {}}Итак, если есть два экземпляра x и y чего -то класса, в чем относится к следующей группе методов одновременно несколько потоков?
axissynca () и x.issyncb ()
bxissynca () и y.issynca ()
cxcsynca () и y.csyncb ()
dxissynca () и что -то.csynca ()
Здесь ясно, что это можно судить:
A, все это синхронизированные доменные доступы к одному и тому же экземпляру (x) и, следовательно, не могут быть доступны одновременно. (Различные синхронизированные домены, которые доступны к X в многопользовании, не могут быть доступны одновременно)
Если x.issynca () доступен в нескольких потоках, поскольку он по -прежнему является одним и тем же экземпляром и заблокирован на одном и том же методе, к нему нельзя получить доступ в нескольких потоках одновременно. (Тот же синхронизированный домен, который обращается к x в многопоточных числах, не может быть доступен одновременно)
b, для разных случаев, поэтому можно получить доступ одновременно (блокировки объектов не имеют ограничений блокировки для разных экземпляров объектов)
C, поскольку это статический синхронизирован, разные случаи все еще будут ограничены, что эквивалентно чем -то. issynca () и что -то.
Итак, как насчет D?, Ответ в книге можно получить одновременно. Причина ответа заключается в том, что синхронно заключается в том, что метод экземпляра и метод синхронного класса отличаются от блокировки.
Личный анализ означает, что синхронизированные и статические синхронизированные эквивалентны двум бандам, каждая из которых имеет свой контроль, и нет никаких ограничений друг на друга и может быть доступен одновременно.
Например:
public Class testSynchronized {public synchronized void test1 () {int i = 5; while (i-> 0) {System.out.println (think.currentThread (). getName () + ":" + i); try {thread.sleep (500); } catch (прерывание Exception IE) {}}} public static synchronized void test2 () {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 testSynchronized myT2 = new TestSynchronized (); Thread test1 = new Thread (new Runnable () {public void run () {myT2.test1 ();}}, "test1"); Thread test2 = new Thread (new Runnable () {public void run () {testSynchronized.test2 ();}}, "test2"); test1.start (); test2.start (); // testrunnable tr = new Testrunnable (); // Thread Test3 = новый поток (TR); // test3.start (); }}Test1: 4 Test2: 4 Test1: 3 Test2: 3 Test2: 2 Test1: 2 Test2: 1 Test1: 1 Test1: 0 Test2: 0
Приведенный выше код синхронизирован изменяет статический метод и метод экземпляра одновременно, но результаты выполнения попеременно выполняются, что доказывает, что блокировки класса и блокировки объектов представляют собой два разных замка, управляющие различными областями, и они не мешают друг другу. Точно так же, в то время как потоки получают блокировки объектов, они также могут получить этот тип блокировки, то есть они получают два замка одновременно, что разрешено.
в заключение:
A: Синхронизированный статик является областью определенного класса. Синхронизированный статический CSYNC {} предотвращает несколько экземпляров в нескольких потоках, чтобы получить доступ к синхронизированному статическому методу в этом классе одновременно. Он работает на всех экземплярах объекта класса.
B: Синхронизированный - это область применения экземпляра. Синхронизированный issync () {} не позволяет этому экземпляру добраться до синхронизированного метода этого класса одновременно.
На самом деле, это очень просто суммировать.
2. Разница между синхронизированным методом и синхронизированным кодом быстро
Не существует различий между синхронизированными методами () {} и синхронизированным (this) {}, но синхронизированные методы () {} удобно для понимания прочитанного, в то время как синхронизированный (это) {} может более точно контролировать области конфликта, а иногда и эффективно выполнять.
Сравнение эффективности между двумя методами:
1. Синхронизируйте блок, код выглядит следующим образом:
Импорт java.util.concurrent.countdownlatch; импортировать java.util.concurrent.executorservice; импортировать java.util.concurrent.executors; открытый класс testSynchronized { / ** * @param args * / public static void main (string [] args) {receemorservice service = executors.newcachedthreadpool (); Окончательный отсчетный отсчетов cdorder = new Countdownlatch (1); Final Countdownlatch cdanswer = new Countdownlatch (3); Final SynconizedClass SC = new SynchonizedClass (); for (int i = 0; i <3; i ++) {runnable runnable = new Runnable () {public void run () {try {cdorder.await (); sc.start (); cdanswer.countdown (); } catch (Exception e) {e.printstackTrace (); }}}; Service.execute (Runnable); } try {thread.sleep ((long) (math.random ()*10000)); System.out.println ("Thread" + Thread.currentThread (). GetName () + "Опубликовать команду выполнения"); cdorder.countdown (); long bomintime = System.currentTimeMillis (); System.out.println ("Thread" + Thread.currentThread (). GetName () + "Команда была отправлена, ожидая результата"); cdanswer.await (); System.out.println ("Thread" + Thread.currentThread (). GetName ()) + "Все результаты ответа были получены, время взято:" + (System.CurrentTimeMillis ()-BERINTIME)); } catch (Exception e) {e.printstackTrace (); } service.shutdown (); }} class synchonizedclass {public void start () throws urruptEdException {thread.sleep (100); // Выполнить другую логику для потребления времени синхронизированного времени (this) {System.out.println ("I запустил ее с 10 мс"); }}} Результаты работы следующие:
Поток основной выпускает команду выполнения, Main поток отправил команду, ожидая результата, который я запустил и использовал 10 мс.
Я бегу с использованием 10 мс
Я бегу с использованием 10 мс
Основной поток получил все результаты ответа, и время, занятое: 110
Метод синхронизации, код выглядит следующим образом:
Импорт java.util.concurrent.countdownlatch; импортировать java.util.concurrent.executorservice; импортировать java.util.concurrent.executors; открытый класс testSynchronized { / ** * @param args * / public static void main (string [] args) {receemorservice service = executors.newcachedthreadpool (); Окончательный отсчетный отсчетов cdorder = new Countdownlatch (1); Final Countdownlatch cdanswer = new Countdownlatch (3); Final SynconizedClass SC = new SynchonizedClass (); for (int i = 0; i <3; i ++) {runnable runnable = new Runnable () {public void run () {try {cdorder.await (); sc.start (); cdanswer.countdown (); } catch (Exception e) {e.printstackTrace (); }}}; Service.execute (Runnable); } try {thread.sleep ((long) (math.random ()*10000)); System.out.println ("Thread" + Thread.currentThread (). GetName () + "Опубликовать команду выполнения"); cdorder.countdown (); long bomintime = System.currentTimeMillis (); System.out.println ("Thread" + Thread.currentThread (). GetName () + "Команда была отправлена, ожидая результата"); cdanswer.await (); System.out.println ("Thread" + Thread.currentThread (). GetName ()) + "Все результаты ответа были получены, время взято:" + (System.CurrentTimeMillis ()-BERINTIME)); } catch (Exception e) {e.printstackTrace (); } service.shutdown (); }} class synchonizedclass {public synchronized void start () throws urpruptException {thread.sleep (100); // Выполнить другое логическое время // synchronized (this) {System.out.println ("I использовал 10 мс"); //}}}Результаты работы следующие:
Поток основной выпускает команду выполнения, Main поток отправил команду, ожидая результата, который я запустил и использовал 10 мс.
Я бегу с использованием 10 мс
Я бегу с использованием 10 мс
Основной поток получил все результаты ответа, и время, которое нужно: 332
Разница между ними: 222 мс.
Сравнение показывает, что синхронные кодовые блоки более эффективны, чем методы синхронизации.
Дополнительная память:
1. Есть две области синхронизированных ключевых слов:
1) Это в экземпляре объекта. Синхронизированный amethod () {} может предотвратить доступ к нескольким потокам добраться до синхронизированного метода этого объекта одновременно (если у объекта есть несколько синхронизированных методов, если один поток обращается к одному из синхронизированных методов, другие потоки не могут получить любые синхронизированные методы в объект одновременно). В настоящее время синхронизированный метод различных экземпляров объекта непрерывно. То есть другие потоки все еще могут получить доступ к синхронизированному методу в другом экземпляре объекта того же класса одновременно;
2) Это область определенного класса. Синхронизированный статический astaticmethod {} предотвращает различные объекты экземпляра (или один и тот же объект экземпляра) в нескольких потоках, чтобы получить доступ к синхронизированному статическому методу в этом классе одновременно. Он работает на всех экземплярах объекта класса.
2. В дополнение к использованию синхронизированного ключевого слова перед методом, синхронизированное ключевое слово также можно использовать в блоке в методе, что указывает на то, что в ресурсах этого блока выполняется только взаимоисключительный доступ. Использование: Synchronized (this) {/*block*/} (или синхронизированный (obj) {/*block*/}), и его область является текущим объектом;
3. Синхронизированное ключевое слово нельзя унаследовать. То есть метод синхронизированного класса базового класса f () {} не является автоматически синхронизированный f () {} в унаследованном классе, но становится f () {}. Класс наследования требует, чтобы вы явно указали, что один из его методов синхронизирован;
Некоторое понимание синхронизированного (это) (хорошо объясните блокировку объекта, обратите внимание на это ключевое слово в нем)
1. Когда два параллельных потока получают доступ к этому синхронизированному (этому) синхронизированному кодовому блоку в одном объекте объекта, в течение одного времени можно выполнить только один поток. Другой поток должен ждать, пока текущий поток выполнит этот кодовый блок, прежде чем он сможет выполнить кодовый блок.
2. Однако, когда один поток обращается к синхронизированному (этой) кодовому блоку синхронизации объекта, другой поток все еще может получить доступ к несинхронизированному (это) блоку кода синхронизации в этом объекте.
3. Особенно важно, чтобы, когда поток обращается к синхронизированному (это) блоку синхронизации объекта, другие потоки будут блокировать доступ ко всем другим блокам синхронизированной (этой) синхронизации в объекте.
4. Третий пример также относится к другим блокам синхронного кода. То есть, когда поток обращается к синхронизированному (этой) кодовому блоку синхронизации объекта, он получает блокировку объекта этого объекта. В результате другие потоки доступа ко всем частям синхронного кода объекта объекта временно заблокированы.
5. Приведенные выше правила также применяются к другим блокировкам объектов.
Добавьте кусок кода, чтобы облегчить тестирование синхронизированных ключевых слов (простая модификация)
public class testsynchronized {public void test1 () {synchronized (this) {int i = 5; while (i-> 0) {System.out.println (think.currentThread (). getName () + ":" + i); try {thread.sleep (500); } catch (прерывание Exception IE) {}}}} публичный синхронизированный void test2 () {int i = 5; while (i-> 0) {System.out.println (think.currentThread (). getName () + ":" + i); try {thread.sleep (500); } catch (прерывание Exception IE) {}}} public Synchronized void test3 () {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 testSynchronized myT2 = new TestSynchronized (); Окончательный тестсинхронизированный myt3 = new TestSynchronized (); Thread Test1 = новый поток (new Runnable () {public void run () {myT2.test2 ();}}, "test1"); Thread test2 = new Thread (new Runnable () {public void run () {myt2.test3 ();}}, "test3"); test1.start () ;; test2.start (); }} Результаты работы:
Test1: 4test1: 3test1: 2test1: 1test1: 0test3: 4test3: 3test3: 2test3: 1test3: 0
Ниже мы сосредотачиваемся на использовании сихронизированного в Java, что конкретно: метод синхронизации и синхронизированное блок -синхронизированное ключевое слово, которое включает в себя два использования: синхронизированный метод и синхронизированный блок.
1. Синхронизированный метод: объявить синхронизированный метод, добавив синхронизированное ключевое слово в объявление метода. нравиться:
общественный синхронизированный void accessval (int newval);
Синхронизированный метод управляет доступом к переменным элемента класса: каждый экземпляр класса соответствует блокировке, и каждый синхронизированный метод должен получить блокировку экземпляра класса, который вызывает метод, прежде чем его можно будет выполнить. В противном случае, нить, к которой он принадлежит, заблокирована. Как только метод будет выполнен, он будет занимать исключительно замок. Замок не будет выпущен, пока не вернется из метода. Заблокированный поток может получить блокировку и повторно ввести исполняемое состояние. Этот механизм гарантирует, что в то же время, для каждого экземпляра класса, в большинстве случаев одну из всех функций -членов, объявленных синхронизированными, находится в исполняемом состоянии (поскольку в большинстве случаев можно получить блокировку, соответствующую экземпляру класса), что эффективно избегает конфликтов доступа переменных членов класса (до тех пор, пока все возможные методы доступа к классу объявляют синхронизируемые).
В Java, не только экземплярах класса, каждый класс также соответствует блокировке, поэтому мы можем объявить статическую функцию элемента класса статической синхронизированной для управления его доступом к статическим переменным элемента класса.
Недостаток синхронизированного метода: объявление большого метода как синхронизированный, значительно повлияет на эффективность. Как правило, если метод класса потока run () объявляется синхронизированным, поскольку он работает на протяжении всего срока службы потока, он приведет к тому, что он никогда не будет успешным ни в каком синхронизированном методе этого класса. Конечно, мы можем решить эту проблему, поместив код, который обращается к переменным члена класса в специальный метод, объявляя его синхронизированным, и вызывая его в основном методе, но Java предоставляет нам лучшее решение, то есть синхронизированный блок.
2. Синхронизированный блок: объявить синхронизированный блок через синхронизированное ключевое слово. Синтаксис выглядит следующим образом:
Synchronized (Syncobject) {// код, который позволяет управлять доступом} Синхронизированный блок - это кодовый блок, в котором код должен получить блокировку синкобата объекта (как упоминалось ранее, это может быть экземпляр класса или класс), прежде чем его можно будет выполнить. Конкретный механизм такой же, как описано выше. Поскольку он может быть нацелен на любой кодовый блок, и заблокированные объекты могут быть указаны в любое время, он более гибкий.
Уведомление:
При использовании синхронизированных ключевых слов вам следует избегать использования методов сна или урожая в синхронизированных методах или синхронизированных блоках как можно больше, потому что синхронизированные программные блоки занимают блокировки объектов, поэтому, если вы отдыхаете, другие потоки могут быть выполнены только при ожидании, когда вы проснетесь и завершит выполнение. Это не только серьезно влияет на эффективность, но и не логично.
Точно так же не имеет смысла называть метод yeild в блоке синхронного программы, чтобы отказаться от ресурса ЦП, потому что вы занимаете блокировку и другие потоки Mutex по -прежнему не могут получить доступ к блоку синхронного программы. Конечно, потоки, которые не связаны с синхронными блоками программы, могут получить больше времени выполнения.
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.