What Happens if Same Object Instance Is Read by Two Threads
One of the almost common situations in concurrent programming occurs when more than one execution thread shares a resources. In a concurrent application, information technology is normal for multiple threads to read or write the same information structure or have admission to the same file or database connection. These shared resources tin provoke mistake situations or data inconsistency, and we have to implement some machinery to avoid these errors. These situations are calledrace atmospheric condition and they occur when unlike threads have access to the same shared resources at the aforementioned fourth dimension.
Therefore, the final result depends on the order of the execution of threads, and near of the fourth dimension, it is incorrect. You tin can also have issues with change visibility. Then if a thread changes the value of a shared variable, the changes would only be written in the local cache of that thread; other threads will non take access to the modify (they will only exist able to see the old value).
We present to you a java multithreading tutorial taken from the book, Coffee nine Concurrency Cookbook – Second Edition, written by Javier Fernández González.
The solution to these issues lies in the concept of a disquisitional section. A critical department is a block of code that accesses a shared resources and can't be executed by more than one thread at the same fourth dimension. To assistance programmers implement critical sections, Java (and virtually all programming languages) offers synchronization mechanisms. When a thread wants access to a disquisitional section, information technology uses ane of these synchronization mechanisms to discover out whether there is any other thread executing the disquisitional section.
If non, the thread enters the critical department. If yep, the thread is suspended by the synchronization mechanism until the thread that is currently executing the critical section ends it. When more than than ane thread is waiting for a thread to finish the execution of a critical department, JVM chooses one of them and the residual look for their plough.
Java language offers two bones synchronization mechanisms:
- Thesynchronized keyword
- TheLock interface and its implementations
In this article, nosotros explore the use ofsynchronized keyword method to perform synchronization mechanism in Java.
So let's go started:
Synchronizing a method
In this recipe, you volition acquire how to utilise one of the nigh basic methods of synchronization in Java, that is, the apply of thesynchronized keyword to control concurrent access to a method or a block of code. All thesynchronized sentences (used on methods or blocks of lawmaking) use an object reference. Only ane thread can execute a method or block of code protected by the aforementioned object reference.
When you use thesynchronized keyword with a method, the object reference is implicit. When you use thesynchronized keyword in one or more methods of an object, merely ane execution thread will have admission to all these methods. If another thread tries to admission whatsoever method declared with thesynchronized keyword of the same object, information technology will be suspended until the first thread finishes the execution of the method.
In other words, every method alleged with thesynchronized keyword is a disquisitional section, and Java only allows the execution of ane of the critical sections of an object at a fourth dimension. In this example, the object reference used is theown object, represented by thethis keyword. Static methods have a different behavior. Merely one execution thread will have access to one of the static methods declared with thesynchronized keyword, but a different thread tin access other non-static methods of an object of that class.
You take to be very careful with this point because two threads tin can access two differentsynchronized methods if one is static and the other is non. If both methods change the same data, you tin can accept data inconsistency errors. In this case, the object reference used is the class object.
When you utilize thesynchronized keyword to protect a block of code, you must laissez passer an object reference equally a parameter. Normally, you lot will use thethis keyword to reference the object that executes the method, merely yous tin use other object references too. Usually, these objects will be created exclusively for this purpose. Y'all should continue the objects used for synchronization private.
For instance, if you have two contained attributes in a course shared by multiple threads, you must synchronize admission to each variable; however, it wouldn't be a problem if one thread is accessing one of the attributes and the other accessing a unlike aspect at the same time. Have into account that if you use theown object (represented by thethis keyword), y'all might interfere with other synchronized code (as mentioned before, thethis object is used to synchronize the methods marked with thesynchronized keyword).
In this recipe, yous volition learn how to apply thesynchronized keyword to implement an application simulating a parking area, with sensors that discover the following: when a car or a motorbike enters or goes out of the parking area, an object to shop the statistics of the vehicles being parked, and a mechanism to control cash catamenia. We will implement two versions: one without whatever synchronization mechanisms, where we will encounter how we obtain wrong results, and one that works correctly as it uses the two variants of thesynchronized keyword.
The case of this recipe has been implemented using the Eclipse IDE. If you use Eclipse or a unlike IDE, such as NetBeans, open up information technology and create a new Java project.
How to practise it…
Follow these steps to implement the example:
- First, create the application without using any synchronization mechanism. Create a class namedParkingCash with an internal constant and an attribute to shop the full corporeality of money earned by providing this parking service:
public class ParkingCash { individual static final int cost=2; private long cash; public ParkingCash() { cash=0; } - Implement a method namedvehiclePay() that volition be called when a vehicle (a car or motorbike) leaves the parking area. Information technology volition increase the cash attribute:
public void vehiclePay() { cash+=cost; } - Finally, implement a method namedclose() that volition write the value of the greenbacks attribute in the console and reinitialize it to zero:
public void close() { System.out.printf("Closing bookkeeping"); long totalAmmount; totalAmmount=cash; cash=0; System.out.printf("The full amount is : %d", totalAmmount); } } - Create a class namedParkingStats with three private attributes and the constructor that will initialize them:
public class ParkingStats { individual long numberCars; private long numberMotorcycles; private ParkingCash greenbacks; public ParkingStats(ParkingCash cash) { numberCars = 0; numberMotorcycles = 0; this.greenbacks = cash; } - Then, implement the methods that will be executed when a car or motorbike enters or leaves the parking area. When a vehicle leaves the parking area, greenbacks should be incremented:
public void carComeIn() { numberCars++; } public void carGoOut() { numberCars--; cash.vehiclePay(); } public void motoComeIn() { numberMotorcycles++; } public void motoGoOut() { numberMotorcycles--; greenbacks.vehiclePay(); } - Finally, implement two methods to obtain the number of cars and motorcycles in the parking area, respectively.
- Create a class namedSensor that will simulate the movement of vehicles in the parking area. Information technology implements theRunnable interface and has aParkingStats attribute, which will be initialized in the constructor:
public class Sensor implements Runnable { individual ParkingStats stats; public Sensor(ParkingStats stats) { this.stats = stats; } - Implement therun() method. In this method, simulate that 2 cars and a motorcycle arrive in and then leave the parking expanse. Every sensor will perform this activity ten times:
@Override public void run() { for (int i = 0; i< 10; i++) { stats.carComeIn(); stats.carComeIn(); try { TimeUnit.MILLISECONDS.sleep(l); } catch (InterruptedException e) { e.printStackTrace(); } stats.motoComeIn(); try { TimeUnit.MILLISECONDS.slumber(l); } catch (InterruptedException e) { due east.printStackTrace(); } stats.motoGoOut(); stats.carGoOut(); stats.carGoOut(); } }
- Finally, implement the main method. Create a class namedMain with theprimary() method. It needsParkingCash andParkingStats objects to manage parking:
public class Main { public static void main(Cord[] args) { ParkingCash greenbacks = new ParkingCash(); ParkingStats stats = new ParkingStats(cash); System.out.printf("Parking Simulatorn"); - Then, create theSensor tasks. Utilize theavailableProcessors() method (that returns the number of available processors to the JVM, which normally is equal to the number of cores in the processor) to calculate the number of sensors our parking expanse will have. Create the correspondingThread objects and store them in an array:
intnumberSensors=2 * Runtime.getRuntime() .availableProcessors(); Thread threads[]=new Thread[numberSensors]; for (int i = 0; i<numberSensors; i++) { Sensor sensor=new Sensor(stats); Thread thread=new Thread(sensor); thread.beginning(); threads[i]=thread; } - Then wait for the finalization of the threads using thejoin() method:
for (int i=0; i<numberSensors; i++) { try { threads[i].join(); } take hold of (InterruptedException e) { e.printStackTrace(); } } - Finally, write the statistics ofParking:
Organisation.out.printf("Number of cars: %dn", stats.getNumberCars()); System.out.printf("Number of motorcycles: %dn", stats.getNumberMotorcycles()); cash.close(); } } In our case, we executed the example in a four-core processor, so we will accept eightSensor tasks. Each job performs 10 iterations, and in each iteration, three vehicles enter the parking area and the same iii vehicles go out. Therefore, eachSensor task will simulate 30 vehicles.
If everything goes well, the final stats will show the following:
- There are no cars in the parking area, which means that all the vehicles that came into the parking surface area have moved out
- EightSensor tasks were executed, where each task simulated 30 vehicles and each vehicle was charged 2 dollars each; therefore, the full corporeality of greenbacks earned was 480 dollars
When you execute this instance, each time yous will obtain different results, and most of them will be incorrect. The following screenshot shows an example:
Nosotros had race weather, and the different shared variables accessed by all the threads gave incorrect results. Permit's modify the previous code using the synchronized keyword to solve these problems:
- Start, add the synchronized keyword to thevehiclePay() method of theParkingCash form:
public synchronized void vehiclePay() { cash+=cost; } - Then, add asynchronized block of code using thethis keyword to theclose() method:
public void shut() { System.out.printf("Closing accounting"); long totalAmmount; synchronized (this) { totalAmmount=cash; cash=0; } System.out.printf("The total amount is : %d",totalAmmount); } - Now add two new attributes to theParkingStats class and initialize them in the constructor of the grade:
private concluding Object controlCars, controlMotorcycles; public ParkingStats (ParkingCash cash) { numberCars=0; numberMotorcycles=0; controlCars=new Object(); controlMotorcycles=new Object(); this.cash=cash; } - Finally, change the methods that increment and decrement the number of cars and motorcycles, including thesynchronized keyword. ThenumberCars attribute will be protected by thecontrolCars object, and thenumberMotorcycles aspect will be protected by thecontrolMotorcycles object. You must besides synchronize thegetNumberCars() andgetNumberMotorcycles() methods with the associated reference object:
public void carComeIn() { synchronized (controlCars) { numberCars++; } } public void carGoOut() { synchronized (controlCars) { numberCars--; } cash.vehiclePay(); } public void motoComeIn() { synchronized (controlMotorcycles) { numberMotorcycles++; } } public void motoGoOut() { synchronized (controlMotorcycles) { numberMotorcycles--; } cash.vehiclePay(); } - Execute the case at present and see the difference when compared to the previous version.
How it works…
The following screenshot shows the output of the new version of the example. No matter how many times yous execute information technology, y'all will always obtain the correct result:
Let'due south encounter the different uses of thesynchronized keyword in the example:
- First, we protected thevehiclePay() method. If two or more thanSensor tasks call this method at the aforementioned time, only ane volition execute information technology and the rest will look for their plough; therefore, the final amount will always exist correct.
- Nosotros used two different objects to control access to the car and motorcycle counters. This way, oneSensor task can modify thenumberCars attribute and anotherSensor task can modify thenumberMotorcycles attribute at the same time; however, no 2Sensor tasks will be able to change the same attribute at the same time, so the final value of the counters will always exist correct.
Finally, we too synchronized thegetNumberCars() andgetNumberMotorcycles() methods. Using thesynchronized keyword, we can guarantee correct access to shared data in concurrent applications.
As mentioned at the introduction of this recipe, merely one thread tin can access the methods of an object that uses thesynchronized keyword in their declaration. If thread (A) is executing asynchronized method and thread (B) wants to execute anothersynchronized method of the same object, it will be blocked until thread (A) is finished. But if thread (B) has access to unlike objects of the same class, none of them will be blocked.
When you use thesynchronized keyword to protect a cake of code, yous use an object as a parameter. JVM guarantees that merely one thread can have access to all the blocks of lawmaking protected with this object (note that we e'er talk nigh objects, non classes).
We used theTimeUnit class too. TheTimeUnit form is an enumeration with the following constants:DAYS,HOURS,MICROSECONDS,MILLISECONDS,MINUTES,NANOSECONDS, andSECONDS. These indicate the units of fourth dimension we pass to the sleep method. In our case, we allow the thread slumber for fifty milliseconds.
There'due south more…
Thesynchronized keyword penalizes the performance of the awarding, so you must only utilize it on methods that change shared data in a concurrent environs. If you have multiple threads calling asynchronized method, merely one will execute them at a time while the others will remain waiting.
If the operation doesn't use thesynchronized keyword, all the threads can execute the operation at the same time, reducing the total execution fourth dimension. If you know that a method will non be called by more than one thread, don't use thesynchronized keyword. Anyhow, if the class is designed for multithreading admission, information technology should always be right. You must promote definiteness over performance. Too, you should include documentation in methods and classes in relation to their thread rubber.
You can use recursive calls withsynchronized methods. As the thread has access to thesynchronized methods of an object, you can call othersynchronized methods of that object, including the method that is being executed. It won't have to get admission to thesynchronized methods once again.
Nosotros can apply thesynchronized keyword to protect admission to a cake of code instead of an entire method. We should use thesynchronized keyword in this way to protect admission to shared data, leaving the residuum of the operations out of this block and obtaining meliorate functioning of the application. The objective is to take the disquisitional section (the block of lawmaking that can exist accessed simply past one thread at a fourth dimension) every bit short every bit possible.
Besides, avoid calling blocking operations (for example, I/O operations) inside a critical section. We have used thesynchronized keyword to protect admission to the instruction that updates the number of persons in the building, leaving out the long operations of the block that don't use shared data. When you use thesynchronized keyword in this style, you must laissez passer an object reference every bit a parameter. Only one thread tin access thesynchronized code (blocks or methods) of this object. Normally, we will utilize thethis keyword to reference the object that is executing the method:
synchronized (this) { // Java lawmaking } To summarize, we learnt to apply the synchronized keyword method for multithreading in Java to perform synchronization mechasim.
Yous read an excerpt from the volume Java 9 Concurrency Cookbook – Second Edition. This book will help you master the fine art of fast, effective Java development with the power of concurrent and parallel programming.
Read Side by side:
Concurrency programming 101: Why exercise programmers hang past a thread?
How to create multithreaded applications in Qt
Getting Inside a C++ Multithreaded Application
What Happens if Same Object Instance Is Read by Two Threads
Source: https://hub.packtpub.com/java-multithreading-synchronize-threads-implement-critical-sections/
Post a Comment for "What Happens if Same Object Instance Is Read by Two Threads"