In Java, one way to synchronize threads is to use the Synchronized keyword, which can be used to decorate a block of code, as follows:
synchronized (Locked synchronization object) {// code block: Business code }
When synchronized is used to modify a block of code, it means that if more than one thread is executing this block of code, it needs to wait until one of the threads finishes executing and the second thread executes it. But! If the locked synchronization object is not selected correctly, the above conclusion is incorrect.
What kind of object can be a lock object (also called a synchronization object)? We should always pay attention to the following points when selecting a synchronization object:
1th, objects that need to be locked are visible in multiple threads, the same object
"Visible" It is obvious that if an object is not visible, it cannot be locked. "The same object", which is understandable, if the object is not locked, then how to synchronize two objects? However, we do not have to make mistakes on this. To illustrate this recommendation, let's first simulate a scenario where the lock must be used: The train station sells train tickets. A train a total of 100 tickets, a total of 3 windows at the same time to sell tickets, the code is as follows:
PackageCom.zuikc.thread; Public classSYNCHRONIZEDSAMPLE01 { Public Static voidMain (string[] args) {//CreateTicketwindow Window1 =NewTicketwindow ("Ticket window 1"); Ticketwindow Window2=NewTicketwindow ("Ticket window 2"); Ticketwindow window3=NewTicketwindow ("Ticket window 3"); Window1.start (); Window2.start (); Window3.start (); }}classTicketwindowextendsThread {//a total of 100 seats Static intTicket = 100; PublicTicketwindow (String name) {Super(name); } @Override Public voidrun () {//Mock Sell ticket while(Ticket > 0) {System.out.println ( This. GetName () + "sell seat Number:" +ticket); Ticket--; Try{Thread.Sleep (10); } Catch(interruptedexception e) {e.printstacktrace (); } } }}
However, after running, we found that some of our train tickets were sold several times, such as:
As long as you run a few more times, we'll see different results. But almost every time there is a number of seats to be sold several times the phenomenon occurs.
Some students may say, simple: Add synchronized Lock synchronization object, so we modify the code:
classTicketwindowextendsThread {//a total of 100 seats Static intTicket = 100; //defining a locked synchronization objectObject obj =NewObject (); PublicTicketwindow (String name) {Super(name); } @Override Public voidrun () {//blocks of code that you want to synchronize synchronized(obj) {//Mock Sell ticket while(Ticket > 0) {System.out.println ( This. GetName () + "sell seat Number:" +ticket); Ticket--; Try{Thread.Sleep (10); } Catch(interruptedexception e) {e.printstacktrace (); } } } }}
After running, we found no change in the results. Why is that?
Because in 3 threads, we are not locking the same object.
We see that the lock is an instance variable, as follows:
Object obj = new Object ();
The existence of three threads means that 3 obj is generated, and each thread locks the 3 different obj objects, so the synchronization code block is equal to not being synchronized.
So what should I do? The simplest approach is that we can change the instance variable to a member variable, the static variable, as follows:
Static Object obj = new Object ();
Then, run the ticket code and find out how to solve the problem. Don't believe it, try it.
Second note: In a non-static method, a static variable should not be used as a synchronization object
Just finished, to fix the example in the 1th, you need to change obj to static. This seems to be in contradiction with this note. In fact, the example code in the 1th is for demonstration purposes only, and when writing multithreaded code, we can follow the principle that static methods of a type should ensure thread safety, and non-static methods do not need to implement thread safety. And if the syncobject becomes static, which is equivalent to having a non-static method with thread safety, the problem is that if there are multiple instances of that type in the application, there will be synchronization when this lock is encountered, which may not be what we were willing to see.
3rd: Value type (base data type) object cannot be used as a synchronization object
In fact, such code is not compiled.
A value type creates a copy when passing another thread, which is equivalent to two objects locked by each thread. Therefore, a value type object cannot be a synchronization object. This can actually be attributed to the 1th.
4th, locking strings is completely unnecessary, and quite dangerous
This whole process looks exactly the opposite of the value type. The string will be staged into memory in the virtual machine, and if there are two variables assigned to the same content string, then the two references will be pointed to the same piece of memory. So, if you have two locations that use synchronized ("ABC"), then they actually lock the same object, causing the entire application to be blocked.
5th: Reduce the visibility of synchronization objects
Synchronizing objects in general, should not be a public variable, we should always consider reducing the visibility of synchronization objects, the synchronization of our objects to hide, only open to their own or their own sub-class is enough (it is not uncommon to open to subclasses).
The following is the ad time: most courses (zuikc.com) are recruiting Java Employment Class students, if you want to learn more Java high-quality code writing skills, please contact us oh.
Java Code Quality Improvement: synchronization object Selection