Java multi threaded synchronous locking mechanism and synchronized in depth analysis

  • 2020-04-01 02:15:42
  • OfStack

For example: an object is like a big house, the door is always open. There are many rooms in the house. These rooms are either locked (synchronized methods) or unlocked (normal methods). There is a key at the door of the room, which can open all the locked rooms. In addition, I liken all threads that want to call methods on this object to people who want to enter a room in this house. So that's all, so let's see how these things work together.

So let's be clear about our preconditions. The object has at least one synchronized method, otherwise the key is meaningless. Of course, we wouldn't have this topic.

A man wants to enter a locked room. He goes to the door of the house and sees the key. So he went up and got the keys and used the rooms according to his plan. Note that he will return the key to the locked room as soon as he has used it. Even if he had to use two locked rooms in a row, he had to return the key and get it back.

Therefore, the general principle of the use of keys is: "borrow as you use, use up and return."

There is no restriction on the use of unlocked rooms by other people, one room for one person, one room for two people, no restriction. But if a man wants to enter a locked room, he has to run to the door. Of course you take the key and go. If you don't, you have to wait.

If a lot of people are waiting for the key, who will get it first when the key is returned? Not guaranteed. Like the guy in the previous example who tried to use two locked rooms in a row, if someone else was waiting for the key while he returned it, there was no guarantee that the guy would get it again. (the JAVA specification makes it clear in many places that there are no guarantees, such as how long thread.sleep () will return to run after a break, the Thread with the same priority will be executed first, which of the multiple threads in the wait pool will get first when the lock to access the object is released, and so on. I think it's ultimately up to the JVM to decide, and the reason it's not guaranteed is because the JVM is making these decisions based not on one condition, but on many. However, due to too many judgment conditions, if said may affect the promotion of JAVA, it may also be because of the reason of intellectual property protection. SUN gave me a no guarantee and got away with it. Fair enough. But I believe these uncertainties, not all uncertainties. Because the computer itself runs on command. Even seemingly random phenomena are actually regular. Anyone who has studied computers knows that the scientific name of a random number in a computer is a pseudorandom number. Plus, maybe it's because it takes too much work and doesn't make much sense to be sure, so you don't have to be sure.)

Now let's look at the synchronized block. It's a little different from the synchronization method.

1. In terms of size, the synchronized code block is smaller than the synchronized method. You can think of a synchronized block of code as a space in an unlocked room separated by a locked screen.

2. The synchronized block can also be manually specified to obtain the key of some other object. Just like specifying which key to use to unlock this screen, you can use the key of this room; You can also specify that you use the key of another house to open it, in which case you have to run to another house to get the key and use the key of that house to open the locked screen of this house.

Remember that the key to the other house you acquired does not prevent others from entering the unlocked room of that house.

Why use synchronized blocks of code? I think it should be like this: first of all, the synchronous part of the program is very inefficient, and a method is usually to create some local variables, then do some operations on these variables, such as operation, display, etc.; The more code a synchronization covers, the greater the impact on efficiency. So we usually try to minimize its impact. How to do? Synchronize code blocks. We only synchronize the steps in a method, such as operations.

In addition, the feature that synchronized blocks can specify keys has the added benefit of being able to hog an object's key for a certain period of time. Remember we talked about the general principles of keys. This is no ordinary situation. The key you get is not never returned, but returned when you exit the synchronized block.

Or the guy in the front who wants to use two locked rooms in a row. How can I continue to use another room after using one? Use synchronized blocks of code. Create another thread, make a synchronized block, and point the lock of that block to the key of the house. Then start that thread. As long as you can catch the key to the house when you enter the code block, you can keep it until you exit the code block. That means you can even walk through and even sleep(10*60*1000) all the locked rooms in your room, while there are 1000 threads waiting for the key at the door. That was fun.

Here's how the sleep() method relates to the key. If a thread is forced to sleep() after it gets the key and does not complete the synchronization, the key is still there. It won't return the key until it runs again and does all the synchronization. Remember, the guy just got tired of working and went to rest. He didn't finish what he was about to do. To prevent others from entering the room and making a mess of it, he wore the only key on his back even while he slept.

Finally, one might ask, why a key, rather than a key and a door? I think it's purely a matter of complexity. One key to the door is safer, but there are a lot of problems involved. Key generation, custody, acquisition, return, etc. The complexity may increase geometrically with the increase of synchronization methods, which seriously affects the efficiency. It's a tradeoff. How undesirable it is to add a little bit of security, resulting in a huge loss of efficiency.


Related articles: