В многопоточном программировании наиболее важной и наиболее заинтересованной проблемой должна быть проблема синхронизации, которая является сложной точкой и ядром.
От синхронизированной и изменчивой из самой ранней версии JDK, до интерфейса блокировки в пакете java.util.concurrent.locks, предоставленной в JDK 1.5 (реализации включают в себя чтение, WriteLock и Reentrantlock), реализация с несколькими потоками также постепенно созревает.
Какой механизм используется для контроля синхронизации? Первой реакцией является блокировка, которая должна была быть подвержена воздействию при изучении операционной системы и базы данных. В многопоточных программах Java, когда несколько программ конкурируют за один и тот же ресурс, чтобы предотвратить коррозию ресурсов, первое поток, получающую доступ к ресурсу, назначается блокировкой объекта, а более позднее поколения должны ждать выпуска этого блокировки объекта.
Да, наиболее заинтересованной в синхронизации потоков Java является использование общих ресурсов.
Давайте сначала поймем некоторые общие ресурсы, из которых доступны потоки.
Из JVM нам нужно координировать данные, разделяемые потоками:
1. переменная экземпляра, сохранившаяся в куче; 2. Переменная класса, сохранившаяся в области метода.
Когда виртуальная машина Java загружает класс, каждый объект или класс будут связаны с монитором для защиты переменной экземпляра объекта или переменной класса; Конечно, если у объекта нет переменных экземпляра, или у класса нет переменных, монитор ничего не будет контролировать.
Чтобы достичь мутекс, упомянутого выше, виртуальная машина связывает блокировку (также называемую невидимой блокировкой) для каждого объекта или класса. Позвольте мне объяснить здесь, что блокировки класса также реализованы через блокировки объектов, потому что, когда класс загружен, JVM создаст экземпляр java.lang.class для каждого класса; Поэтому, когда блокировка против объекта, объект класса этого класса заблокирован.
Кроме того, поток может заблокировать объект несколько раз, что соответствует нескольким выпускам; Это калькулятор блокировки, предоставленный JVM для каждой блокировки объекта. Последняя блокировка добавлена 1, и соответствующий минус 1, и когда значение калькулятора составляет 0, оно выделяется. Эта блокировка объекта используется монитором внутри JVM и также автоматически генерируется JVM. Все программисты не должны добавлять его сами по себе.
После введения принципа синхронизации Java мы перейдем к теме и первым поговорим об использовании синхронизации. Другие синхронизации будут представлены в следующих главах.
Давайте сначала попробуем запустить пример.
пакет thread_test; / *** Проверка многопоточных программ, которые расширяют реализацию потока класса**/ public class testthread extends {private int threadnum; public TestThread (int Threadnum) {this.Threadnum = ThreadNum; } @Override public synchronized void run () {for (int i = 0; i <1000; i ++) {System.out.println ("no." + Threadnum + ":" + i); }} public static void main (string [] args) бросает исключение {for (int i = 0; i <10; i ++) {new TestThread (i) .start (); Thread.sleep (1); }}}
Результаты работы:
№ 0: 887 № 0: 888 № 0: 889 № 0: 890 № 0: 891 № 0: 892 № 0: 893 № 0: 894 № 7: 122 № 7: 123 № 7: 124
Выше приведено просто клип, объясняющий проблему.
Если вы осторожны, вы обнаружите, что № 0: 894 следит за № 7: 122, что означает, что он не начинается с 0 до 999.
Говорят, что синхронизированный может реализовать методы синхронизации или блоки синхронизации, почему он не может работать здесь?
Давайте сначала проанализируем механизм синхронизации. Синхронизация достигается посредством блокировки. Итак, в приведенном выше примере, какой объект заблокирован или какой класс заблокирован? Внутри есть две переменные, одна - это я, а другая - нить; Я внутренний для метода, а Threadnum является частным.
Давайте узнаем о механизме синхронизации:
В программе Java, когда используется синхронизированный блок или синхронизированный метод, эта область отмечена для мониторинга; В то время как, когда JVM обрабатывает программу, когда программа входит в область мониторинга, она автоматически заблокирует объект или класс.
Итак, в приведенном выше примере, что заблокировано после использования синхронизированного ключевого слова?
При синхронизированном методе заблокируйте объект экземпляра, который называет сам метод как блокировку объекта. В этом примере 10 потоков имеют свои собственные объекты класса TestThread, поэтому приобретенная блокировка объекта также является его собственной блокировкой объекта и не имеет ничего общего с другими потоками.
Для реализации блокировки методов общие объекты должны быть заблокированы.
Измените пример выше, а затем посмотрите:
пакет thread_test; / *** Проверка многопоточных программ, которые расширяют реализацию потока класса**/ public class testthread extends {private int threadnum; частный струнный флаг; // Mark Public TestThread (int Threadnum, String Flag) {this.Threadnum = ThreadNum; this.flag = flag; } @Override public void run () {synchronized (flag) {for (int i = 0; i <1000; i ++) {System.out.println ("no." + Threadnum + ":" + i); }}} public static void main (string [] args) бросает исключение {String flag = new String ("flag"); for (int i = 0; i <10; i ++) {new TestThread (i, flag) .start (); Thread.sleep (1); }}}
Это также добавляется общий флаг. Затем флаг флага синхронизируется через синхронизированный блок; Это соответствует условиям для блокировки общего объекта.
Да, результаты работы пришли в порядке.
Через синхронизированный блок укажите получение блокировки объектов для достижения синхронизации. Так есть ли другие методы, которые могут быть реализованы с помощью синхронизированного метода?
Согласно принципу синхронизации: если можно получить блокировку общего объекта или блокировку класса, может быть достигнута синхронизация. Так можем ли мы достичь этого, поделившись блокировкой класса?
Да, мы можем использовать методы статической синхронизации. Согласно характеристикам статических методов, он только позволяет вызывать самого объекта класса и не может быть вызвано путем создания объекта класса. Затем, если вы получите блокировку этого статического метода, вы получите блокировку класса, и эта блокировка этого класса является все блокировки класса TestThread, и достигается цель получения общих замков класса.
Код реализации выглядит следующим образом:
пакет thread_test; / ** * Проверка многопоточных программ, которые расширяют реализацию класса потоков * * @author carding * @createtime 7 декабря 2011 г. 9:37:25 * *// public class testthread extends {private int threadnum; public TestThread (int Threadnum) {this.Threadnum = ThreadNum; } public Static Synchronized void Statictest (int threadnum) {for (int i = 0; i <1000; i ++) {System.out.println ("no." + threadnum + ":" + i); }} public static void main (string [] args) бросает исключение {for (int i = 0; i <10; i ++) {new TestThread (i) .start (); Thread.sleep (1); }} @Override public void run () {statictest (threadnum); }} Результат прогона опущен, так же, как во втором примере.
Вышеуказанный контент в основном объясняет две проблемы: блоки синхронизации и методы синхронизации.
1. Синхронизированный блок: Полученная блокировка объекта является блокировкой объекта флага в синхронизированном (FLAG).
2. Метод синхронизации: объект класса, к которому принадлежит метод, и блокировка объекта класса.
Метод статической синхронизации, безусловно, будет синхронизирован, так как будет использоваться несколько потоков.
Вместо статических методов синхронизации они будут синхронизировать только в режиме Синглтона.