Java static и потоки

Многопоточность Java и статические методы

Факты доказали, что до тех пор, пока многопоточные общие данные не обрабатываются в статической функции, не возникает проблемы конфликтов ресурсов, когда многопоточный доступ к одному и тому же статическому методу , Смотрите пример ниже:

public class StaticThread implements Runnable < @Override public void run() < // TODO Auto-generated method stub StaticAction.print(); >public static void main(String[] args) < for (int i = 0; i < 100; i++) < new Thread(new StaticThread()).start(); >> >
public class StaticAction < public static int i = 0; public static void print() < int sum = 0; for (int i = 0; i < 10; i++) < System.out.print("step " + i + " is running."); sum += i; >if (sum != 45) < System.out.println("Thread error!"); System.exit(0); >System.out.println("sum is " + sum); > >

Диаграмма эффекта операции выглядит следующим образом:

Мы можем видеть, что доступ каждого потока к статическому методу Перекрестное выполнение Из, но это не Не влияет Статический метод print () в каждом потоке sum Расчет стоимости. Другими словами, статические методы, которые не используют глобальные переменные во время этого процесса, безопасны в многопоточности, То, вызывает ли статический метод проблемы с безопасностью потока, зависит в основном от того, модифицирует ли статический метод глобальную переменную (статический член статической переменной)

При использовании одного и того же статического метода в нескольких потоках каждый поток использует каждый из Копия поля экземпляра И Общий Статическое поле , Таким образом, если статический метод не работает на статическом члене, только Внутри метода использование Поле экземпляра , Не вызовет проблем с безопасностью.

Читайте также:  Python regexp начало строки

Однако, если статический метод работает со статической переменной, его необходимо использовать в статическом методе. Взаимоисключающий доступ Безопасное обращение. Давайте посмотрим на проблемы, которые могут возникнуть, если вы не используете взаимоисключающий доступ:

public class StaticAction < public static int i = 0; public static void incValue() < int temp = StaticAction.i; try < Thread.sleep(1); >catch (Exception e) < e.printStackTrace(); >temp++; StaticAction.i = temp; > >
public class StaticThread implements Runnable < @Override public void run() < // TODO Auto-generated method stub StaticAction.incValue(); >public static void main(String[] args) < for (int i = 0; i < 100; i++) < new Thread(new StaticThread()).start(); >try < Thread.sleep (1000); // Зарезервировать достаточно времени для завершения вышеупомянутого потока >catch (Exception e) < e.printStackTrace(); >System.out.println(StaticAction.i); > >

Здесь мы можем увидеть проблему. Для достижения взаимоисключающего доступа нам нужно добавить synchronized Ключевые слова. Код изменяется следующим образом:

public class StaticAction < public static int i = 0; public synchronized static void incValue() < int temp = StaticAction.i; try < Thread.sleep(1); >catch (Exception e) < e.printStackTrace(); >temp++; StaticAction.i = temp; > >
public class StaticThread implements Runnable < @Override public void run() < // TODO Auto-generated method stub StaticAction.incValue(); >public static void main(String[] args) < for (int i = 0; i < 100; i++) < new Thread(new StaticThread()).start(); >try < Thread.sleep(1000); >catch (Exception e) < e.printStackTrace(); >System.out.println(StaticAction.i); > >

Результаты таковы, на этот раз проблем не будет:

присоединиться synchronized Статический метод ключевых слов называется Синхронный статический метод

При доступе к синхронизированному статическому методу получается объект «Класс» этого класса, поэтому, когда поток входит в синхронизированный статический метод, монитор потока получает Блокировка объектаДругие потоки не могут вводить статический метод синхронизации этого класса , Это не похоже на методы экземпляра, потому что несколько потоков могут одновременно обращаться к различным методам экземпляра синхронизации экземпляра Это на самом деле в операционной системе Использование семафоров для достижения взаимного исключения и синхронизации процессов Вопрос, если это связано Тот же класс Там Несколько статических методов Если вы хотите обрабатывать многопоточные общие данные, они становятся Решить проблемы производителя-потребителя с семафорами , Другими словами, статический метод является копией Критический ресурс Доступ к статическим методам принадлежит Критическая зона ; Модификация статических переменных является критическим ресурсом, а модификация статических переменных относится к критической области.

Источник

Tech Tutorials

Tutorials and posts about Java, Spring, Hadoop and many more. Java code examples and interview questions. Spring code examples.

Thursday, July 8, 2021

Static Synchronization in Java Multi-Threading

With instance method synchronization, threads are executed one thread per instance. That may create problems when we have more than one instance of the same class. In that scenario you may have to synchronize at the class level if you want to have a single lock for all the instances of the class rather than synchronizing at object level. That is what static synchronization in Java does.

  • static synchronized method
  • An enclosed synchronized code block with in a static method.

Synchronized static method in Java

Synchronized instance method is synchronized on the instance(object) of the class. If a class has two objects, then two threads can acquire lock on these two objects and enter the synchronized method or block at the same time.

Synchronized static method Java example

Here we have a class Message whose object will be shared among threads. In class Message there is a method displayMsg. You want one thread to finish printing the message with in the method then only another thread should start executing the method. Here two objects of Message1 class, msg1 and msg2 are created. Then four threads are created out of which two threads share the msg1 object where as the other two share the msg2 object.

First let’s see with the help of an example what problem we may face in case we don’t use static synchronization.

Code without static synchronization

//This class' shared object will be accessed by threads class Message1 < public synchronized void displayMsg()< System.out.println("In run method " + Thread.currentThread().getName()); for(int i = 0; i < 5 ; i++)< System.out.println(Thread.currentThread().getName() + " i - " + i); try < Thread.sleep(50); >catch (InterruptedException e) < // TODO Auto-generated catch block e.printStackTrace(); >> > > class MyClass1 implements Runnable < Thread t; Message1 msg; MyClass1(Message1 msg)< this.msg = msg; t = new Thread(this); t.start(); >@Override public void run() < msg.displayMsg(); >> public class SynchronizedDemo1 < public static void main(String[] args) < Message1 msg1 = new Message1(); Message1 msg2 = new Message1(); // Two threads on msg1 object MyClass1 mc1 = new MyClass1(msg1); MyClass1 mc2 = new MyClass1(msg1); // Two threads on msg2 object MyClass1 mc3 = new MyClass1(msg2); MyClass1 mc4 = new MyClass1(msg2); >>
In run method Thread-1 Thread-1 i - 0 In run method Thread-3 Thread-3 i - 0 Thread-3 i - 1 Thread-1 i - 1 Thread-3 i - 2 Thread-1 i - 2 Thread-1 i - 3 Thread-3 i - 3 Thread-3 i - 4 Thread-1 i - 4 In run method Thread-2 Thread-2 i - 0 In run method Thread-0 Thread-0 i - 0 Thread-0 i - 1 Thread-2 i - 1 Thread-0 i - 2 Thread-2 i - 2 Thread-2 i - 3 Thread-0 i - 3 Thread-0 i - 4 Thread-2 i - 4

Here it can be seen that thread-0 and thread-1 are invoked on msg1 object where as thread-2 and thread-3 are invoked on msg-2 object.

As we already know if you are using synchronization on the instance methods then the thread will have exclusive lock one per instance. In the given example two of the threads share one object and another two share another object thus thread-0 and thread-1 will be synchronized using one monitor and thread-2 and thread-3 are synchronized using another monitor.

We can see in the output thread-0 and thread-1 are not having any thread interference same way thread 2 and thread-3 are not having any thread interference but thread-1 and thread-3 are entering the synchronized method at the same time with their own respective locks. Lock hold by thread-1 will stop thread-0 from entering the synchronized method as they are working on the same instance. But it cannot stop thread-2 or thread-3 as they are working on another instance.

Code with static synchronized method

In these kinds of scenarios if we still want that a synchronized method or block is accessed by a single thread then we have to use static synchronized method or block to have synchronization at the class level rather than on the instance level.

As we know that every class loaded by the JVM is essentially an object of type Class. So, in that case too, monitor of the object is acquired but that is the monitor of the Class object that represents the class to which the static method belongs.

We just need to change the displayMsg() method to make it a static method-

//This class' shared object will be accessed by threads class Message1 < public static synchronized void displayMsg()< System.out.println("In run method " + Thread.currentThread().getName()); for(int i = 0; i < 5 ; i++)< System.out.println(Thread.currentThread().getName() + " i - " + i); try < Thread.sleep(50); >catch (InterruptedException e) < e.printStackTrace(); >> > >
In run method Thread-0 Thread-0 i - 0 Thread-0 i - 1 Thread-0 i - 2 Thread-0 i - 3 Thread-0 i - 4 In run method Thread-2 Thread-2 i - 0 Thread-2 i - 1 Thread-2 i - 2 Thread-2 i - 3 Thread-2 i - 4 In run method Thread-3 Thread-3 i - 0 Thread-3 i - 1 Thread-3 i - 2 Thread-3 i - 3 Thread-3 i - 4 In run method Thread-1 Thread-1 i - 0 Thread-1 i - 1 Thread-1 i - 2 Thread-1 i - 3 Thread-1 i - 4

It can be seen now how threads are executing one after another with any one thread holding the lock while it is executing.

static synchronized block in Java

Same way we can have static synchronized block where we need to synchronize the class object itself.

Java static synchronized block syntax

Synchronized(CLASS_NAME.class)

static synchronized block Java example

If we take the previous example itself and make it a static synchronized block instead of static synchronized method then Message1 class will look like

//This class' shared object will be accessed by threads class Message1 < public static void displayMsg()< System.out.println("In run method " + Thread.currentThread().getName()); synchronized(Message1.class)< for(int i = 0; i < 5 ; i++)< System.out.println(Thread.currentThread().getName() + " i - " + i); try < Thread.sleep(50); >catch (InterruptedException e) < e.printStackTrace(); >> > > >
In run method Thread-0 In run method Thread-3 Thread-0 i - 0 In run method Thread-1 In run method Thread-2 Thread-0 i - 1 Thread-0 i - 2 Thread-0 i - 3 Thread-0 i - 4 Thread-2 i - 0 Thread-2 i - 1 Thread-2 i - 2 Thread-2 i - 3 Thread-2 i - 4 Thread-1 i - 0 Thread-1 i - 1 Thread-1 i - 2 Thread-1 i - 3 Thread-1 i - 4 Thread-3 i - 0 Thread-3 i - 1 Thread-3 i - 2 Thread-3 i - 3 Thread-3 i - 4

See how the first statement is printed for all the threads as that statement is outside the synchronized block. But only thread-0 acquires the lock and starts its execution, all the other threads are suspended till the execution of thread-0 finishes.

That’s all for this topic Static Synchronization in Java Multi-Threading. If you have any doubt or any suggestions to make please drop a comment. Thanks!

Источник

Оцените статью