- How to make a method thread-safe in Java?
- Related posts:
- Is static method is thread safe in Java?
- Is static code thread safe?
- What is thread safe and non thread safe in Java?
- Is Java list thread safe?
- What is thread-safe and non thread-safe in Java?
- What is thread safe Java?
- What happens if I use static method in multithreading Java?
- How to make a collection thread safe in Java?
- Java thread safe static methods
- Достоинства
- Недостатки
How to make a method thread-safe in Java?
Is the following method thread-safe? How to make it thread-safe?
class MyCounter { private static int counter = 0; public static int getCount() { return counter++; } }
This post explains a general interview question that has been asked by Google and a lot of companies. It’s low-level and not about how to design concurrent program.
First of all, the answer is NO. The method is not thread-safe, because the counter++ operation is not atomic, which means it consists more than one atomic operations. In this case, one is accessing value and the other is increasing the value by one.
When Thread 1 accesses the method at t1, Thread 2 may not be done with the method. So the value returned to Thread 1 is the value that has not been increased.
Make a method thread-safe — Method 1
Adding synchronized to this method will makes it thread-safe. When synchronized is added to a static method, the Class object is the object which is locked.
Is marking it synchronized enough? The answer is YES.
class MyCounter { private static int counter = 0; public static synchronized int getCount() { return counter++; } }
If the method is not static, then adding synchronized keyword willsynchronize the instance of the class, not the Class object.
Make a method thread-safe — Method 2
In this particular counter example, we actually can make count++ atomic by using AtomicInteger from the package «java.util.concurrent.atomic».
import java.util.concurrent.atomic.AtomicInteger; public class MyCounter { private static AtomicInteger counter = new AtomicInteger(0); public static int getCount() { return counter.getAndIncrement(); } }
Some other useful facts about thread-safe
Local variables are thread safe in Java.
Each thread has its own stack. Two different threads never shares the same stack. All local variables defined in a method will be allocated memory in stack. As soon as method execution is completed by the current thread, stack frame will be removed.
Related posts:
If you want someone to read your code, please put the code inside
and
tags. For example:
Is static method is thread safe in Java?
The static keyword in Java simply means “without regard or knowledge of any particular instance of an object.” So while thread confinement of an object is a valid thread safety policy for instances of a class, this same reasoning is invalid for static methods because they have no instance.
Is static code thread safe?
Ironically static methods are the one type of code that is generally not thread safe by default. Unlike an instance method, static methods can only rely on the parameters their given and static fields. Static fields are shared by all threads and therefore must be made thread safe if the data is being changed.
How do you make a static variable thread safe in Java?
There are basically four ways to make variable access safe in shared-memory concurrency:
- Confinement. Don’t share the variable between threads.
- Immutability. Make the shared data immutable.
- Threadsafe data type.
- Synchronization.
Why static is not thread safe?
Thread Safety Instance variables do not require thread synchronization unless shared among threads. But, static variables are always shared by all the threads in the process. Hence, access to static variable is not thread safe.
What is thread safe and non thread safe in Java?
When multiple threads are working on the same data, and the value of our data is changing, that scenario is not thread-safe and we will get inconsistent results. When a thread is already working on an object and preventing another thread on working on the same object, this process is called Thread-Safety.
Is Java list thread safe?
In fact, all collection classes (except Vector and Hashtable) in the java. util package are not thread-safe. That’s why the new collections (List, Set, Map, etc) provide no concurrency control at all to provide maximum performance in single-threaded applications.
How do you make a method thread safe in Java?
How to make Thread-Safe code in Java. There are multiple ways to make this code thread-safe in Java: 1) Use the synchronized keyword in Java and lock the getCount() method so that only one thread can execute it at a time which removes the possibility of coinciding or interleaving.
Is REST API thread-safe?
REST APIs are naturally multi-thread, once they can execute multiple requests at the same time. Therefore, every time you put a thread to wait for something synchronously you are wasting CPU time because that thread could be being used to handle another request.
What is thread-safe and non thread-safe in Java?
What is thread safe Java?
thread-safety or thread-safe code in Java refers to code that can safely be utilized or shared in concurrent or multi-threading environment and they will behave as expected.
What is thread and thread-safe?
If a class can be safely used on only one thread, it may be better to do so. For example, Java has two classes that are almost equivalent, StringBuffer and StringBuilder . The difference is that StringBuffer is thread-safe, so a single instance of a StringBuffer may be used by multiple threads at once.
Why is thread safety important in multithreading Java?
What happens if I use static method in multithreading Java?
How to make a collection thread safe in Java?
How to ensure thread safety of utility static method?
Java thread safe static methods
Статические методы. Плюсы и минусы.
Определение
Статическими методами в Java называют такие методы, которые могут быть вызваны без создания экземпляра класса. Например, метод pow () из класса Math является статическим:
//Math.pow returns double, need cast, display 256 int result = (int) Math.pow(2, 8);
При вызове метода Math.pow (х , а) вычисляется степень x числа а. При выполнении этого метода не используется ни один из экземпляров класса Math. Иными словами, у него нет неявного параметра this. Это означает, что в статических методах не используется текущий объект по ссылке this. (А в нестатических методах неявный параметр this ссылается на текущий объект)
Когда следует использовать
- Когда методу не требуется доступ к данным о состоянии объекта, поскольку все необходимые параметры задаются явно (например, в методе Math.pow ()).
- Когда методу требуется доступ лишь к статическим полям класса
NumberFormat currencyFormatter = NumberFormat.getCurrencylnstance(); NumberFormat percentFormatter = NumberFormat.getPercentlnstance(); double x = 0.1; System.out.println(currencyFormatter.format(x)); // выводит $0.10 System.out.println(percentFormatter.format(x)); // выводит 10%
- Конструктору нельзя присвоить произвольное имя. Его имя всегда должно совпадать с именем класса. Так, в классе NumberFormat имеет смысл применять разные имена для разных типов форматирования.
- При использовании конструктора тип объекта фиксирован. Если же применяются фабричные методы, они возвращают объект типа Decimal Format, наследующий свойства из класса NumberFormat.
Особенности применения
Важным моментом является то, что статические методы переопределять (Override) нельзя. Если объявить такой же метод в классе-наследнике (subclass), т.е. метод с таким же именем и сигнатурой, то лишь «спрячется» метод суперкласса (superclass) вместо переопределения. Это явление известно как сокрытие методов (hiding methods). Это означает, что при обращении к статическому методу, который объявлен как в родительском, так и в дочернем классе, во время компиляции всегда будет вызван метод исходя из типа переменной. В отличие от переопределения, такие методы не будут выполнены во время работы программы. Рассмотрим пример:
class Vehicle < public static void kmToMiles(int km) < System.out.println("Внутри родительского класса/статического метода"); >> class Car extends Vehicle < public static void kmToMiles(int km) < System.out.println("Внутри дочернего класса/статического метода "); >> public class Demo < public static void main(String args[]) < Vehicle v = new Car(); v.kmToMiles(10); >>
Вывод в консоль:
Внутри родительского класса/статического метода
Код наглядно демонстрирует: несмотря на то, что объект имеет тип Car, вызван статический метод из класса Vehicle, т.к. произошло обращение к методу во время компиляции. И при этом ошибки во время компиляции не возникло!
Статические методы в JVM
Статические методы и переменные хранились в области Permgen до 8-й версии java. Начиная с 8-й версии, они хранятся в новой область памяти, которая называется Metaspace
Примеры применения статических методов
- Статическим является метод main — точка входа в Java-программе.Если метод main не объявлен как static, то у JVM при создании экземпляра класса возникает неопределённость, поскольку конструкторов у класса может быть несколько и непонятно, какой из них вызвать. Кроме того, в случае нестатического метода, jvm создаёт объект прежде чем вызвать метод main, что может привести к проблемам с дополнительным выделением памяти.
- Начиная с версии Java 8, в интерфейсах можно писать статические методы, которые аналогичны default методам, за исключением того, что нельзя их переопределить в реализуемых классах:
- Статические методы в интерфейсах хороши для методов — утилит, например, проверки на null, сортировки коллекций;
- Нельзя определять статические методы в интерфейсах для метода класса Object, это приводит к сообщению об ошибке: «This static method cannot hide the instance method from Object».
Достоинства и недостатки
Достоинства
- отсутствует необходимость каждый раз создавать новый объект для доступа к таким методам
- удобны для создания методов-утилит
- загружаются единственный раз при запуске JVM
Недостатки
- В отличие от локальных переменных, статические методы НЕ потокобезопасны (Thread-safe) в Java. На практике это одна из наиболее частых причин возникновения проблем связанных с безопасностью мультипоточного программирования. Учитывая что каждый экземпляр класса имеет одну и ту же копию статической переменной, то такая переменная нуждается в защите — «залочивании» классом. Поэтому при использовании статических переменных необходимо убедиться, что они должным образом синхронизированы (synchronized), во избежание проблем, например таких как «состояние гонки» (race condition).
- В отличие от локальных переменных, статические методы НЕ потокобезопасны (Thread-safe) в Java. На практике это одна из наиболее частых причин возникновения проблем связанных с безопасностью мультипоточного программирования. Когда метод синхронизирован, он блокирует объект, если метод статичен, он блокирует класс, поэтому всегда рекомендуется использовать синхронизированный блок для блокировки только тех разделов метода, которые требуют синхронизации.
- Если статические методы ссылаются на статические переменные, они остаются в памяти всё время жизни загрузчика классов, что может привести к утечкам памяти.
- Неудобно тестировать юнит-тестами. Нельзя создавать mock-объекты, потому что при вызове статического метода задаётся имя класса.
- Поскольку статический метод нельзя переопределить, это приводит к нарушению полиморфизма. Это приводит к низкой гибкости в ситуациях, когда в результате изменений поведение статического метода становится полиморфным: Пример: HourlyPayCalculator.calculatePay(employee, overtimeRate) Данная статическая функция тоже выглядит вполне разумно. Она не работает ни с каким конкретным объектом и получает все данные из своих аргументов. Однако нельзя исключать, что эту функцию потребуется сделать полиморфной. Возможно, в будущем потребуется реализовать несколько разных алгоритмов для вычисления почасовой оплаты — скажем, OvertimeHourlyPayCalculator и StraightTimeHourlyPayCalculator. В этом случае данная функция не может быть статической. Ее следует оформить как нестатическую функцию Employee. Как следствие, что в случае реализации полиморфного поведения сложно управлять поведением по условию. Это возможно сделать при помощи двух подходов: передать флаг через параметр метода или установить статический флаг извне. Проблема с первым подходом в том, что приходится изменять сигнатуру для каждого вызывающего объекта, что приводит к усложнению кода по причине добавления новых и новых флагов. Применение второго подхода может привести к загромождению кода установкой и сбросом флагов:
boolean oldFlag = MyUtils.getFlag(); MyUtils.someMethod(); MyUtils.setFlag( oldFlag );
- поведение статических методов не может стать полиморфным;
- статический метод не ссылается на статические поля;
- обеспечена потокозащищённость.