In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains "what are the relevant knowledge points of synchronized". The content of the explanation is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "what are the relevant knowledge points of synchronized"?
Locking mode of synchronized
The essence of synchronized is to lock objects, including instance objects as well as class objects. Common locking methods are written in the following ways:
(1) adding synchronized to a non-static method, for example: public void synchronized test () {}, is equivalent to:
Public void test ()
{
Synchronized (this) {}
}
(2) add synchronized to the static method, which is equivalent to a locked class object, such as synchronized (Test.class) {}
Understanding of object locks:
In theory, each object can be used as a lock and can be a lock object. Each lock object has two queues, one is the ready queue, the other is the blocking queue, the ready queue stores the thread that is about to acquire the lock, and the blocking queue stores the blocked thread. When a thread is notify, it enters the ready queue and waits for the scheduling of the CPU.
The keyword of the Java language, when used to modify a method or a block of code, ensures that at most one thread executes the code at a time.
First, when two concurrent threads access the synchronized (this) synchronous code block in the same object object, only one thread can be executed at a time. Another thread must wait for the current thread to finish executing the code block before it can be executed.
However, when one thread accesses a synchronized (this) synchronization block of object, another thread can still access a non-synchronized (this) synchronization block in that object.
Third, it is especially critical that when one thread accesses a synchronized (this) synchronous code block of object, the access of other threads to all other synchronized (this) synchronous code blocks in object will be blocked.
Fourth, the third example is also applicable to other synchronous code blocks. That is, when a thread accesses a synchronized (this) synchronization block of object, it acquires the object lock of that object. As a result, access by other threads to all parts of the synchronous code of the object object is temporarily blocked.
The above rules are also applicable to other object locks.
Examples are as follows:
First, when two concurrent threads access the synchronized (this) synchronous code block in the same object object, only one thread can be executed at a time. Another thread must wait for the current thread to finish executing the code block before it can be executed.
Package ths
Public class Thread1 implements Runnable {
Public void run () {
Synchronized (this) {
For (int I = 0; I
< 5; i++) { System.out.println(Thread.currentThread().getName() + " synchronized loop " + i); } } } public static void main(String[] args) { Thread1 t1 = new Thread1(); Thread ta = new Thread(t1, "A"); Thread tb = new Thread(t1, "B"); ta.start(); tb.start(); } } 结果: A synchronized loop 0 A synchronized loop 1 A synchronized loop 2 A synchronized loop 3 A synchronized loop 4 B synchronized loop 0 B synchronized loop 1 B synchronized loop 2 B synchronized loop 3 B synchronized loop 4 二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。 package ths; public class Thread2 { public void m4t1() { synchronized(this) { int i = 5; while( i-- >0) {
System.out.println (Thread.currentThread () .getName () + ":" + I)
Try {
Thread.sleep (500)
} catch (InterruptedException ie) {
}
}
}
}
Public void m4t2 () {
Int I = 5
While (iMurt-> 0) {
System.out.println (Thread.currentThread () .getName () + ":" + I)
Try {
Thread.sleep (500)
} catch (InterruptedException ie) {
}
}
}
Public static void main (String [] args) {
Final Thread2 myt2 = new Thread2 ()
Thread T1 = new Thread (new Runnable () {public void run () {myt2.m4t1 ();}}, "T1")
Thread T2 = new Thread (new Runnable () {public void run () {myt2.m4t2 ();}}, "T2")
T1.start ()
T2.start ()
}
}
Results:
T1: 4
T2: 4
T1: 3
T2: 3
T1: 2
T2: 2
T1: 1
T2: 1
T1: 0
T2: 0
Third, it is especially critical that when one thread accesses a synchronized (this) synchronous code block of object, the access of other threads to all other synchronized (this) synchronous code blocks in object will be blocked.
/ / modify the Thread2.m4t2 () method:
Public void m4t2 () {
Synchronized (this) {
Int I = 5
While (iMurt-> 0) {
System.out.println (Thread.currentThread () .getName () + ":" + I)
Try {
Thread.sleep (500)
} catch (InterruptedException ie) {
}
}
}
}
Results:
T1: 4
T1: 3
T1: 2
T1: 1
T1: 0
T2: 4
T2: 3
T2: 2
T2: 1
T2: 0
Fourth, the third example is also applicable to other synchronous code blocks. That is, when a thread accesses a synchronized (this) synchronization block of object, it acquires the object lock of that object. As a result, access by other threads to all parts of the synchronous code of the object object is temporarily blocked.
/ / modify the Thread2.m4t2 () method as follows:
Public synchronized void m4t2 () {
Int I = 5
While (iMurt-> 0) {
System.out.println (Thread.currentThread () .getName () + ":" + I)
Try {
Thread.sleep (500)
} catch (InterruptedException ie) {
}
}
}
Results:
T1: 4
T1: 3
T1: 2
T1: 1
T1: 0
T2: 4
T2: 3
T2: 2
T2: 1
T2: 0
5. The above rules are also applicable to other object locks:
Package ths
Public class Thread3 {
Class Inner {
Private void m4t1 () {
Int I = 5
While (iMurt-> 0) {
System.out.println (Thread.currentThread () .getName () + ": Inner.m4t1 () =" + I)
Try {
Thread.sleep (500)
} catch (InterruptedException ie) {
}
}
}
Private void m4t2 () {
Int I = 5
While (iMurt-> 0) {
System.out.println (Thread.currentThread () .getName () + ": Inner.m4t2 () =" + I)
Try {
Thread.sleep (500)
} catch (InterruptedException ie) {
}
}
}
}
Private void m4t1 (Inner inner) {
Synchronized (inner) {/ / use object locks
Inner.m4t1 ()
}
Private void m4t2 (Inner inner) {
Inner.m4t2 ()
}
Public static void main (String [] args) {
Final Thread3 myt3 = new Thread3 ()
Final Inner inner = myt3.new Inner ()
Thread T1 = new Thread (new Runnable () {public void run () {myt3.m4t1 (inner);}}, "T1")
Thread T2 = new Thread (new Runnable () {public void run () {myt3.m4t2 (inner);}}, "T2")
T1.start ()
T2.start ()
}
}
Results:
Although thread T1 acquires an object lock on Inner, thread T2 accesses an unsynchronized part of the same Inner. So the two threads do not interfere with each other.
T1: Inner.m4t1 () = 4
T2: Inner.m4t2 () = 4
T1: Inner.m4t1 () = 3
T2: Inner.m4t2 () = 3
T1: Inner.m4t1 () = 2
T2: Inner.m4t2 () = 2
T1: Inner.m4t1 () = 1
T2: Inner.m4t2 () = 1
T1: Inner.m4t1 () = 0
T2: Inner.m4t2 () = 0
Now add synchronized before Inner.m4t2 ():
Private synchronized void m4t2 () {
Int I = 5
While (iMurt-> 0) {
System.out.println (Thread.currentThread () .getName () + ": Inner.m4t2 () =" + I)
Try {
Thread.sleep (500)
} catch (InterruptedException ie) {
}
}
}
Results:
Although threads T1 and T2 access two unrelated parts of the same Inner object, because T1 first acquires an object lock on Inner, T2 access to Inner.m4t2 () is blocked because m4t2 () is a synchronization method in Inner.
T1: Inner.m4t1 () = 4
T1: Inner.m4t1 () = 3
T1: Inner.m4t1 () = 2
T1: Inner.m4t1 () = 1
T1: Inner.m4t1 () = 0
T2: Inner.m4t2 () = 4
T2: Inner.m4t2 () = 3
T2: Inner.m4t2 () = 2
T2: Inner.m4t2 () = 1
T2: Inner.m4t2 () = 0
The second article:
Synchronized keyword, which includes two uses: the synchronized method and the synchronized block.
1. Synchronized method: declare the synchronized method by adding the synchronized keyword to the method declaration. Such as:
Public synchronized void accessVal (int newVal)
The synchronized method controls access to class member variables: each class instance corresponds to a lock, and each synchronized method must acquire the lock of the class instance that called the method.
Otherwise, the thread to which it belongs blocks, and once the method is executed, the lock is monopolized and the lock is not released until it is returned from the method, after which the blocked thread can acquire the lock and re-enter the executable
Status. This mechanism ensures that at most one of all member functions declared as synchronized is executable for each class instance at a time (because at most only
A lock corresponding to the instance of this class can be obtained, thus effectively avoiding access conflicts of class member variables (as long as all possible methods to access class member variables are declared as synchronized)
.
In Java, not only the class instance, but also each class corresponds to a lock, so we can also declare the static member function of the class as synchronized to control its static property to the class.
Access to member variables.
The drawback of the synchronized method: declaring a large method as synchronized will greatly affect efficiency. Typically, the thread class's method run () is declared as
Synchronized, because it has been running throughout the lifetime of the thread, will cause its calls to any synchronized methods of this class to never succeed. Of course we can.
To solve this problem by placing code that accesses class member variables in a special method, declaring it as synchronized, and calling it in the main method, but Java provides us with
A better solution is the synchronized block.
2. Synchronized blocks: declare synchronized blocks through the synchronized keyword. The syntax is as follows:
Synchronized (syncObject) {
/ / allow access control code
}
A synchronized block is a block of code in which the code must acquire a lock on the object syncObject (which, as mentioned earlier, can be an instance of a class or a class) before it can be executed.
The system is the same as mentioned above. Because it can be targeted at any code block and the locked object can be specified arbitrarily, it is more flexible.
Some understanding of synchronized (this)
First, when two concurrent threads access the synchronized (this) synchronous code block in the same object object, only one thread can be executed at a time. Another line
The program must wait for the current thread to execute the code block before it can execute the code block.
However, when one thread accesses a synchronized (this) synchronization block of object, another thread can still access non-synchronized in that object
(this) synchronize blocks of code.
Third, it is particularly critical that when one thread accesses a synchronized (this) synchronization block of object, other threads respond to all other synchronized (this) in the object
Access to the synchronous code block will be blocked.
Fourth, the third example is also applicable to other synchronous code blocks. That is, when a thread accesses a synchronized (this) synchronization block of object, it gets this
Object lock for object. As a result, access by other threads to all parts of the synchronous code of the object object is temporarily blocked.
5. The above rules are also applicable to other object locks
Http://hi.baidu.com/sunshibing/blog/item/5235b9b731d48ff430add14a.html
The usage of synchronized in java
For example: an object is like a big house, the door is always open. There are many rooms (that is, methods) in the house.
These rooms can be locked (synchronized method) and unlocked (common method). There is a key (key) at the door, which can open all locked rooms.
In addition, I compare all the threads that want to call the object method to people who want to enter a room in the house. That's all. Let's see how these things work.
Here, let's clarify our prerequisites. The object has at least one synchronized method, otherwise the key is meaningless. Of course, there would not be our theme.
A man wants to enter a locked room. He comes to the door of the house and sees the key there (indicating that no one else is using the locked room yet). So he went up and got the key.
And use those rooms according to your own plan Note that every time he uses the locked room, he will return the key immediately. Even if he had to use two locked rooms in a row
In the middle, he also wants to return the key and get it back.
Therefore, in general, the principle for the use of keys is: "borrow as you like, and return it as soon as you use it."
At this time, other people can use those unlocked rooms without restrictions, one for one person and one for two people, without restriction. But if someone wants to get into a locked room,
In a few minutes, he was about to run to the gate to have a look. If you have the key, of course you'll take it and go. If you don't have it, you'll have to wait.
If many people are waiting for this key, who will get the key first when the key is returned? Not guaranteed . Like the guy in the previous example who wants to use two locked rooms in a row, he
If someone else is waiting for the key in the middle, there is no guarantee that this guy will get it again. (the JAVA specification makes it clear that there is no guarantee in many places, such as
How long will Thread.sleep () return to run after the rest? the thread with the same priority will be executed first, and which of the multiple threads in the waiting pool will have priority when the lock on the object to be accessed is released.
Here we go. Wait. I think the final decision rests with JVM. The reason why it is not guaranteed is that when JVM makes the above decision, it is by no means simply based on one condition, but
According to a lot of rules. Due to too many judgment conditions, if we say it may affect the promotion of JAVA, it may also be due to the protection of intellectual property rights. SUN made a promise to muddle through.
. no ground for blame. But I believe these uncertainties are not at all uncertain. Because the computer itself runs according to instructions. Even if it seems to be a random phenomenon, it is actually regular.
Can be found. Anyone who has studied the computer knows that the scientific name of the random number in the computer is a pseudo-random number, which is written by people using certain methods, and looks random. Besides, maybe it's because if you want to do it
It is too troublesome to make sure, and it doesn't make much sense, so if you are not sure, you are not sure. )
Let's take a look at the synchronization code block. There is a slight difference from the synchronization method.
1. In terms of size, the synchronization code block is smaller than the synchronization method. You can think of a synchronous code block as a space separated by a locked screen in an unlocked room.
two。 The synchronization block can also artificially specify the key of some other object. Just like specifying which key can be used to open the lock of this screen, you can use the key of this room; you can also specify
You can only open it with the key of another house, so you have to run to another house to get that key and use the key of that house to open the locked screen of this house.
Remembering that you got the key to the other house does not prevent others from entering the unlocked room of the house.
Why use synchronous code blocks? I think it should be like this: first of all, the synchronization part of the program affects the running efficiency, and one method is usually to create some local changes first.
Quantity, and then do some operations on these variables, such as operation, display, and so on; and the more code covered by synchronization, the more serious the impact on efficiency. So we usually try to minimize its scope of influence.
How to do it? Synchronize code blocks. We synchronize only the places in a method that should be synchronized, such as operations.
In addition, the feature that synchronous code blocks can specify keys has the added benefit of being able to occupy the key of an object for a certain period of time. Remember that I said earlier that under normal circumstances, the key
The principle of using the key. It's not normal anymore. The key you got is not returned forever, but only when you exit the synchronized code block.
And compare it to the guy in front who wants to use two locked rooms in a row. How can I continue to use one after using another? Use synchronization code blocks. Create another first
A thread, making a synchronous code block, points the lock of that code 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 that code block.
You can keep it until you exit that block of code In other words, you can even go through all the locked rooms in the room, even sleep (10-60-1000), while there are still at the door.
1000 threads are waiting for this key. It was fun.
Let's talk about the relationship between the sleep () method and the key here. When a thread gets the key and does not complete the synchronized content, if it is forced to sleep (), the key will return
Straight to it. The key will not be returned until it runs again and all the synchronized content is done. Remember, that guy is just tired of working. Go and have a rest. He didn't finish what he had to do. For
To prevent others from entering the room and making a mess, he had to wear the only key even when he was sleeping.
Finally, some people may ask, why should one key open instead of one key to one door? I think it's purely because of complexity. One key, one door, of course.
It's safe, but it involves a lot of problems. The generation, storage, acquisition, return of keys, etc. Its complexity may increase geometrically with the increase of synchronization methods, which seriously affects the efficiency. This is also
It's a matter of trade-off. In order to increase a little bit of security, resulting in a great reduction in efficiency, how undesirable.
A simple example of synchronized
Public class TextThread {
Public static void main (String [] args) {
TxtThread tt = new TxtThread ()
New Thread (tt) .start ()
New Thread (tt) .start ()
New Thread (tt) .start ()
New Thread (tt) .start ()
}
}
Class TxtThread implements Runnable {
Int num = 100
String str = new String ()
Public void run () {
Synchronized (str) {
While (num > 0) {
Try {
Thread.sleep (1)
} catch (Exception e) {
E.getMessage ()
}
System.out.println (Thread.currentThread (). GetName ()
+ "this is" + num--)
}
}
}
}
In the above example, Thread.sleep (10) is used to create a time difference, that is, an opportunity for error.
Java's support and synchronization mechanism for multithreading is very popular. It seems that the problem of multithreaded shared data synchronization can be easily solved by using the synchronized keyword. After all, such as
What? -- We need to have an in-depth understanding of the role of the synchronized keyword before we can come to a conclusion.
Generally speaking, the synchronized keyword can be used as a modifier for a function or as a statement within a function, that is, a synchronization method and a synchronous statement block. If you classify it in detail,
Synchronized can act on instance variables, object reference (object references), static functions, and class literals (class name literal constants).
Before going any further, we need to make a few points clear:
A. whether the synchronized keyword is added to a method or an object, the lock it acquires is an object, rather than treating a piece of code or function as a lock-- and the synchronization method is likely to be used by its
The object access of his thread.
B. only one lock per object is associated with it.
C. the realization of synchronization takes a lot of system overhead as a price, and may even cause deadlock, so try to avoid unnecessary synchronization control.
Then let's discuss the impact of different uses of synchronized on the code:
Suppose P1 and P2 are different objects of the same class, and the following synchronization blocks or synchronization methods are defined in this class, and both P1 and P2 can call them.
1. When synchronized is used as a function modifier, the sample code is as follows:
Public synchronized void methodAAA ()
{
/ / … .
}
This is the synchronization method, so which object is synchronized locking at this time? It locks the call to the synchronous method object. That is, when an object P1 is in a different thread
When this synchronization method is executed, mutual exclusion will be formed between them to achieve the effect of synchronization. But another object, P2, generated by the Class to which this object belongs, can be called at will, and this is added.
The method of synchronized keyword.
The sample code above is equivalent to the following code:
Public void methodAAA ()
{
Synchronized (this) / / 1)
{
/ / … ..
}
}
What does the this at (1) mean? It refers to the object that calls this method, such as P1. It can be seen that the essence of the synchronization method is to apply synchronized to object reference. -- that.
Only the thread that gets the P1 object lock can call the P1 synchronization method, but for P2, the P1 lock has nothing to do with it, and the program may get rid of the control of the synchronization mechanism in this case.
Into data confusion: (
2. Synchronization block. The sample code is as follows:
Public void method3 (SomeObject so)
{
Synchronized (so)
{
/ / … ..
}
}
At this point, the lock is the so object, and whoever gets the lock can run the code it controls. You can write a program like this when you have an explicit object as a lock, but when you don't
The exact object acts as a lock, but when you want a piece of code to synchronize, you can create a special instance variable (which has to be an object) to act as a lock:
Class Foo implements Runnable
{
Private byte [] lock = new byte [0]; / / Special instance variable
Public void methodA ()
{
Synchronized (lock) {/ / … }
}
/ / … ..
}
Note: zero-length byte array objects will be more economical to create than any other object-check the compiled bytecode: it only takes three opcodes to generate zero-length byte [] objects, while Object lock
= new Object () requires seven lines of opcode.
3. Apply synchronized to the static function. The sample code is as follows:
Class Foo
{
Public synchronized static void methodAAA () / / synchronous static function
{
/ / … .
}
Public void methodBBB ()
{
Synchronized (Foo.class) / / class literal (class name literal constant)
}
}
The methodBBB () method in the code takes class literal as a lock, which has the same effect as the synchronous static function. The lock obtained is very special, and the current call to the
The class to which the object of the method belongs (Class, instead of a specific object generated by this Class).
I remember that I saw in the book "Effective Java" that using Foo.class and P1.getClass () as synchronous locks is not the same. You cannot use P1.getClass () to achieve the Class of the lock.
Purpose. P1 refers to the object produced by the Foo class.
It can be inferred that if a class defines a static function An of synchronized and an instance function B of synchronized, then the same object Obj of this class
Accessing methods An and B respectively in multithreading does not constitute synchronization because they all have different locks. The lock of method An is the object Obj, and the lock of method B is the Class to which Obj belongs.
The summary is as follows:
Figuring out which object synchronized is locking can help us design safer multithreaded programs.
There are also some tips to make our synchronous access to shared resources more secure:
1. Define the instance variable of private + its get method, instead of defining the instance variable of public/protected. If the variable is defined as public, the object can be externally
Bypass the control of the synchronization method and get it directly, and change it. This is also one of the standard implementations of JavaBean.
2. If the instance variable is an object, such as an array or ArrayList, then the above method is still not safe, because when the outside object gets the instance object through the get method
, and then point it to another object, then the private variable will change, isn't it dangerous. At this point, you need to add the get method to synchronized synchronization, and
Also, only the clone () of the private object is returned-- so that the caller gets a reference to the copy of the object
Thank you for your reading, the above is the content of "what are the relevant knowledge points of synchronized". After the study of this article, I believe you have a deeper understanding of what the relevant knowledge points of synchronized have, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.