текст
При программировании в одновременной среде необходим механизм блокировки для синхронизации операций между несколькими потоками, чтобы обеспечить взаимоисключительный доступ к общим ресурсам. Блокировка может привести к повреждению производительности, что, кажется, хорошо известно. Тем не менее, сама блокировка не приносит большого потребления производительности, а производительность - это в основном процесс получения замков в потоках. Если есть только один поток, конкурирующая за замки, и в настоящее время нет многопоточных конкурентов, то JVM оптимизируется, и потребление производительности, вызванное блокировкой, в основном может быть проигнорировано. Следовательно, стандартизация работы блокировки, оптимизация метода использования блокировки и избежание ненужной конкуренции за нитью, может не только повысить производительность программы, но и избежать вероятности тяги нити, вызванных нерегулярной блокировкой и повышением надежности программы. Следующее объясняет несколько идей оптимизации блокировки.
1. Старайтесь не блокировать метод
Когда блокировка добавляется в нормальную функцию элемента, поток получает блокировку объекта объекта, где находится метод. В это время весь объект будет заблокирован. Это также означает, что если многочисленные методы синхронизации, предоставленные этим объектом, предназначены для разных услуг, то, поскольку весь объект заблокирован, когда один бизнес обрабатывается, другие не связанные бизнес -потоки также должны ждать. В следующем примере показано:
Класс Lockmethod содержит два метода синхронизации, которые вызываются в двух бизнес -процессах:
public class lockmethod {public synchronized void busia () {for (int i = 0; i <10000; i ++) {System.out.println (thread.currentThread (). getName ()+"Дело с бизнесом A:"+i); }} public synchronized void busib () {for (int i = 0; i <10000; i ++) {System.out.println (thread.currentThread (). getName ()+"Сделка с бизнесом B:"+i); }}}Bussa - это класс потоков, используемый для обработки бизнеса и вызовов метода Busia () Lockmethod:
публичный класс Bussb Extends Thread {Lockmethod Lockmethod; void deal (lockmethod lockmethod) {this.lockmethod = lockmethod; } @Override public void run () {super.run (); lockmethod.busib (); }}Класс Testlockmethod использует Thread Bussa и Bussb для бизнес -обработки:
public class testlockmethod Extends {public static void main (string [] args) {lockmethod lockmethod = new lockmethod (); Bussa bussa = new Bussa (); Bussb bussb = new bussb (); bussa.deal (lockmethod); bussb.deal (lockmethod); bussa.start (); bussb.start (); }}При запуске программы вы можете видеть, что во время выполнения резьбы Bussa BussB не может ввести функциональный Bussib (), потому что блокировка объекта LockMethod получается с помощью потока Bussa.
2. Уменьшите блок синхронного кода и заблокируйте только данные
Иногда для удобства программирования некоторые люди синхронизировали большой кусок кода. Если некоторые операции в этом кодовом блоке не связаны с общими ресурсами, их следует размещать за пределами синхронного блока, чтобы не удерживать замки в течение длительного времени, в результате чего другие потоки остаются в состоянии ожидания. Особенно некоторые циктные операции и синхронные операции ввода/вывода. Это означает не только уменьшение блока синхронизации в диапазоне линий кода, но и в логике выполнения, блок синхронизации должен быть уменьшен. Например, добавьте больше условных суждений и синхронизируйте, если они соответствуют условиям, а не проводят условные суждения после синхронизации, чтобы свести к минимуму ненужную логику, входящую в блок синхронизации.
3. Постарайтесь не включать замки в замке
Эта ситуация часто возникает. После того, как поток получает блокировку A, он вызывает метод синхронизации другого объекта в блоке метода синхронизации и получает вторую блокировку. Это может привести к нескольким запросам блокировки в стеке вызовов. В случае многопоточного, это может вызвать очень сложные и трудно анализировать исключения, что приведет к тупикам. Следующий код показывает это:
синхронизированный (a) {synchronized (b) {}}Или метод синхронизации вызывается в блоке синхронизации:
синхронизированный (a) {b b = objarraylist.get (0); b.method (); // это метод синхронизации}Решение состоит в том, чтобы выпрыгнуть и добавить замки и не включать замки:
{B b = null; синхронизированный (a) {b = objarraylist.get (0); } b.method ();} 4. Приватизируйте блокировку и управляйте замок внутри.
Безопаснее использовать блокировку в качестве частного объекта, и его нельзя получить снаружи. Объект может быть заблокирован непосредственно другими потоками, а поток удерживает блокировку объекта объекта, например:
класс A {public void method1 () {}} класс B {public void method1 () {a a = new a (); синхронизированный (a) {// непосредственно блокировать a.method1 (); }}}В этом способе использования блокировка объекта объекта A удерживается внешним, поэтому более опасно позволить блокировке использоваться в нескольких местах снаружи, а также заставляет проблемы считывать логический поток кода. Лучшим способом является управление самими блоками внутри класса и обеспечить операции синхронизации через интерфейсы, когда необходима внешняя синхронная схема:
класс A {частное объект Lock = new Object (); public void method1 () {synchronized (lock) {}}} класс B {public void method1 () {a a = new a (); a.method1 (); }} 5. Выполните соответствующее разложение блокировки
Рассмотрим следующую процедуру:
открытый класс GameServer {public map <string, list <player >> tables = new Hashmap <String, list <player >> (); public void join (Player Player, таблица таблицы) {if (player.getAccountbalance ()> table.getLimit ()) {synchronized (tables) {list <player> tablePlayers = tables.get (table.getid ()); if (tableplayers.size () <9) {TablePlayers.Add (Player); }}}/В этом примере метод соединения использует только одну блокировку синхронизации для получения объекта List <player> в таблицах, а затем определить, составляет ли количество игроков меньше 9. Если это так, добавьте один игрок. Когда в таблицах появляются тысячи списков, соревнование за замки таблиц будет очень жесткой. Здесь мы можем рассмотреть возможность разложения блокировки: после быстрого извлечения данных заблокируйте объект List <player>, чтобы другие потоки могли быстро конкурировать, чтобы получить блокировку объекта таблиц:
открытый класс GameServer {
публичная карта <строка,
Список <player >> tables = new HashMap <String,
Список <player >> ();
public void join (игрок игрок, таблица таблицы) {
if (player.getaccountbalance ()> table.getLimit ()) {
Список <player> tablePlayers = null;
синхронизированный (таблицы) {
TablePlayers = tables.get (table.getId ());
}
синхронизированный (TablePlayers) {
if (tableplayers.size () <9) {
TablePlayers.Add (Player);
}
}
}
}
public void Leave (Игрок игрок, таблица таблицы) {
/*Опущено*/
}
public void createable () {
/*Опущено*/
}
public void Destroytable (таблица таблицы) {
/*Опущено*/
}
}