In our “What’s Concurrency in Java?” tutorial, we realized that issues can happen inside a multi-threaded setting if a number of threads attempt to entry and alter the identical information on the identical time. This can be a major problem, as it may result in execution deadlocks and information corruption. A program that enables a number of threads to vary the identical information construction or objects concurrently is known as being not thread-safe. Conversely, a program that’s thread protected prevents different threads from engaged on the identical object when a thread is already working with it. On this programming tutorial, we look at 4 comparatively straightforward methods of attaining thread security in our Java packages.
In case you missed it, we suggest studying our earlier a part of this sequence on Java threading: What’s Concurrency in Java?
Leap to:
Utilizing Synchronization in Java
The primary approach to make a program thread protected is to make use of Synchronization. Merely put, Synchronization is the method of permitting just one thread at a time to finish a selected operation. It resolves the inconsistency downside by stopping a number of threads from accessing the identical useful resource on the identical time. Synchronization makes use of a synchronized key phrase, which is a particular modifier that creates a block of code often known as a important part.
Right here is an instance Java program that increments a worth by 5 on two separate threads:
package deal com.developer; public class Maths { void add5(int num) { // Create a thread occasion Thread t = Thread.currentThread(); for (int i = 1; i <= 5; i++) { System.out.println(t.getName() + " : " + (num + i)); } } } package deal com.developer; public class Maths2 extends Thread { Maths maths = new Maths(); public void run() { maths.add5(10); } } package deal com.developer; public class SynchronizationDemo { public static void primary(String[] args) { Maths2 maths = new Maths2(); Thread t1 = new Thread(maths); Thread t2 = new Thread(maths); t1.setName("Thread 1"); t2.setName("Thread 2"); t1.begin(); t2.begin(); } }
As anticipated, the incremented worth jumps in all places as every thread accesses the identical variable concurrently:
Thread 1 : 11 Thread 1 : 12 Thread 1 : 13 Thread 2 : 11 Thread 1 : 14 Thread 2 : 12 Thread 2 : 13 Thread 1 : 15 Thread 2 : 14 Thread 2 : 15
Including the synchronized key phrase to the add5() methodology resolves this subject:
public class Maths { synchronized void add5(int num) { // Create a thread occasion Thread t = Thread.currentThread(); for (int i = 1; i <= 5; i++) { System.out.println(t.getName() + " : " + (num + i)); } } }
Now every thread completes its work in flip:
Thread 1 : 11 Thread 1 : 12 Thread 1 : 13 Thread 1 : 14 Thread 1 : 15 Thread 2 : 11 Thread 2 : 12 Thread 2 : 13 Thread 2 : 14 Thread 2 : 15
Learn: Finest Instruments for Java Cellular Improvement
Utilizing the risky Key phrase in Java
One other approach to obtain thread security in Java is to make use of the risky key phrase. It’s a area modifier that ensures that the thing can be utilized by a number of threads on the identical time with out inflicting the problematic behaviors talked about above.
The next instance code declares and instantiates two integers utilizing the risky key phrase:
package deal com.developer; public class VolatileKeywordDemo { static risky int int1 = 0, int2 = 0; static void methodOne() { int1++; int2++; } static void methodTwo() { System.out.println("int1=" + int1 + " int2=" + int2); } public static void primary(String[] args) { Thread t1 = new Thread() { public void run() { for (int i = 0; i < 5; i++) { methodOne(); } } }; Thread t2 = new Thread() { public void run() { for (int i = 0; i < 5; i++) { methodTwo(); } } }; t1.begin(); t2.begin(); } }
As we will observe in this system output, each variables have been totally incremented by the primary thread earlier than the second thread outputs their values:
int1=5 int2=5 int1=5 int2=5 int1=5 int2=5 int1=5 int2=5 int1=5 int2=5
Methods to Use Atomic Variables in Java
One other approach to obtain thread security in Java is to make use of atomic variables. Because the identify suggests, atomic variables enable builders to carry out an atomic operation on a variable. Atomic variables decrease synchronization and assist keep away from reminiscence consistency errors. Probably the most generally used atomic variables are AtomicInteger, AtomicLong, AtomicBoolean, and AtomicReference. Right here is a few instance Java code that makes use of AtomicInteger to increment two separate counters earlier than outputting their mixed worth:
package deal com.developer; import java.util.concurrent.atomic.AtomicInteger; public class Counter { AtomicInteger counter = new AtomicInteger(); public void increment() { counter.incrementAndGet(); } } package deal com.developer; public class AtomicIntegerDemo { public static void primary(String[] args) throws Exception { Counter c = new Counter(); Thread t1 = new Thread(new Runnable() { public void run() { for (int i = 1; i <= 5000; i++) { c.increment(); } } }); Thread t2 = new Thread(new Runnable() { public void run() { for (int i = 1; i <= 5000; i++) { c.increment(); } } }); t1.begin(); t2.begin(); t1.be part of(); t2.be part of(); System.out.println(c.counter); } }
Operating the above program produces an output of “10000“.
Learn: Prime Java Frameworks
Methods to Use the ultimate Key phrase in Java
Ultimate Variables are at all times thread protected in Java as a result of, as soon as assigned, a reference to an object can not level to a different object. Here’s a quick program to reveal how one can use the closing key phrase in Java:
package deal com.developer; public class FinalKeywordDemo { closing String aString = new String("Immutable"); void someMethod() { aString = "new worth"; } }
Built-in growth environments (IDEs) won’t even allow you to run the above code and can present a compiler error concerning the try and reassign a worth to the ultimate aString variable:
Ultimate Ideas on Thread Security in Java
This programming tutorial offered 4 methods of attaining thread security in our Java packages, specifically: utilizing Synchronization, the risky Key phrase, by way of atomic variables, and the closing key phrase. There are different methods to attain thread security in Java, however these require barely extra effort on the a part of the developer. These embody using locks from the java.util.concurrent.locks package deal and utilizing thread protected assortment courses similar to ConcurrentHashMap.
Subsequent Steps
Now that you’ve a agency understanding of a few of the methods to attain thread security in Java, we suggest testing a number of of our different tutorials on threading and multithreading in Java: