Home Java javaTutorial Detailed explanation of java synchronized

Detailed explanation of java synchronized

Dec 13, 2016 am 10:55 AM

Java language keywords, when used to modify a method or a code block, can ensure that at most one thread executes the code at the same time.

1. When two concurrent threads access the synchronized (this) synchronization 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 this code block before it can execute this code block.

2. However, when a thread accesses a synchronized (this) synchronized code block of object, another thread can still access the non-synchronized (this) synchronized code block in the object.

3. What is particularly critical is that when a thread accesses a synchronized (this) synchronized code block of object, other threads will be blocked from accessing all other synchronized (this) synchronized code blocks in object.

4. The third example is also applicable to other synchronization code blocks. That is to say, when a thread accesses a synchronized(this) synchronized code block of object, it obtains the object lock of this object. As a result, other threads' access to all synchronized code parts of the object object is temporarily blocked.

5. The above rules are also applicable to other object locks.

Example:
1. When two concurrent threads access the synchronized (this) synchronization code block in the same object object, there can only be one at a time The thread gets executed. Another thread must wait for the current thread to finish executing this code block before it can execute this code block.

package ths;

public class Thread1 implements Runnable {
                                                                            using using using using using         through using       through   through out through out through out out out through out Through out off   ‐ for   ‐ ‐ ‐‐ ‐ ‐ to System.out.println(Thread .currentThread().getName() + " synchronized loop " + i); 1();
         Thread ta = new Thread (t1, "A");
         Thread tb = new Thread(t1, "B"); 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

2. However, When a thread accesses a synchronized(this) synchronized code block of an object, another thread can still access the non-synchronized(this) synchronized code block in the object.

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( i-- > 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();  
     } 
}

结果:  
     t1 : 4  
     t2 : 4  
     t1 : 3  
     t2 : 3  
     t1 : 2  
     t2 : 2  
     t1 : 1  
     t2 : 1  
     t1 : 0  
     t2 : 0

     三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

Re // Modify Thread2.m4t2 () Method:

Public void M4T2 () {
Synchronized (this) {
int i = 5;
about (i- & gt; 0) {
System.out.println (Thread. currentThread().getName() + " : " + i);                                                                                   ) {
                                                                                                                                                 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3

t2 : 2

t2 : 1

t2 : 0

4. The third example is also applicable to other synchronizations code block. That is to say, when a thread accesses a synchronized(this) synchronized code block of object, it obtains the object lock of this object. As a result, other threads' access to all synchronized code parts of the object object is temporarily blocked.


                                                                                            Thread2.m4t2                                                                                                                                                                                   , .out.println(Thread.currentThread( ).getName() + " : " + i);
                                                                                       ​} }
}
}

Result:
t1 : 4
t1 : 3
t1 : 2

t1 : 1

t1 : 0

t2 : 4

t2 : 3

t2 : 2

t2 : 1
t 2: 0

5. The above rules also apply to other object locks:

package ths;

public class Thread3 { 
     class Inner { 
          private void m4t1() { 
               int i = 5; 
               while(i-- > 0) { 
                    System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i); 
                    try { 
                         Thread.sleep(500); 
                    } catch(InterruptedException ie) { 
                    } 
               } 
          } 
          private void m4t2() { 
               int i = 5; 
               while(i-- > 0) { 
                    System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i); 
                    try { 
                         Thread.sleep(500); 
                    } catch(InterruptedException ie) { 
                    } 
               } 
          } 
     } 
     private void m4t1(Inner inner) { 
          synchronized(inner) { //使用对象锁 
          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(); 
  } 
}

结果:

尽管线程t1获得了对Inner的对象锁,但由于线程t2访问的是同一个Inner中的非同步部分。所以两个线程互不干扰。

     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

现在在Inner.m4t2()前面加上synchronized:

                                                                                  int i = 5; )= " + i);
                                                                                                                                                                                                                                                                                                 
                                                                                                                                                  Irrelevant part, but because t1 first obtained the object lock on Inner, t2's access to Inner.m4t2() is also blocked, because m4t2() is a synchronized method in Inner.

t1 : Inner.m4t1()=4
t1 : Inner.m4t1()=3
t1 : Inner.m4t1()=2
t1 : Inner.m4t1()=1
t1 : Inner.m4t 1()= 0
t2 : Inner.m4t2()=4

t2 : Inner.m4t2()=3

t2 : Inner.m4t2()=2

t2 : Inner.m4t2()=1

t2 : Inner.m4t2 ()= 0

Second article:

synchronized keyword, which includes two usages: synchronized method and synchronized block.
1. synchronized method: declare the synchronized method by adding the synchronized keyword to the method declaration. For example:
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 obtain the lock of the class instance that calls the method

Execution, otherwise the thread to which it belongs is blocked. Once the method is executed, it will exclusively occupy the lock. The lock will not be released until returning from the method. After that, the blocked thread can obtain the lock and re-enter the executable

state. This mechanism ensures that for each class instance at the same time, at most one of all its member functions declared as synchronized is in the executable state (because at most only one can obtain the lock corresponding to the class instance), thus effectively avoiding Access violation of class member variables (as long as all methods that may access class member variables are declared synchronized)

.

In Java, not only class instances, each class also corresponds to a lock. In this way, we can also declare the static member functions of the class as synchronized to control its access to the static member variables of the class. Defects of the

synchronized method: If a large method is declared as synchronized, it will greatly affect the efficiency. Typically, if the thread class method run() is declared as

synchronized, because it has been running for the entire life cycle of the thread. run, thus causing its calls to any synchronized methods of this class to never succeed. Of course we can solve this problem by putting the code that accesses class member variables into a special method, declaring it synchronized, and calling it in the main method, but Java provides us with a better solution The solution is synchronized blocks.
2. synchronized block: declare synchronized block through synchronized keyword. The syntax is as follows:

synchronized(syncObject) {

//Code that allows access control

}

synchronized block is a code block in which the code must obtain the lock of the object syncObject (as mentioned before, it can be a class instance or class) Before it can be executed, the specific mechanism is the same as mentioned above. Because it can target any code block and specify the locked object arbitrarily, it has high flexibility.

Some understanding of synchronized(this)

1. When two concurrent threads access the synchronized(this) synchronization 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 this code block before it can execute this code block.

2. However, when a thread accesses a synchronized(this) synchronized code block of object, another thread can still access the non-synchronized


(this) synchronized code block in the object.

Third, what is particularly critical is that when a thread accesses a synchronized(this) synchronization code block of object, other threads access all other synchronized(this) in object

Access to synchronized code blocks will be blocked.
4. The third example is also applicable to other synchronized code blocks. That is to say, when a thread accesses a synchronized(this) synchronized code block of object, it obtains the object lock of this

object. As a result, other threads' access to all synchronized code parts of the object object is temporarily blocked.
5. The above rules also apply to other object locks

http://hi.baidu.com/sunshibing/blog/item/5235b9b731d48ff430add14a.html
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 are either locked (synchronized method) or unlocked (normal method). There is a key at the door of the room. This key can open all locked rooms.

In addition, I compare all threads that want to call the object's methods to people who want to enter a certain room in this house. That’s all there is to it, let’s take a look at how these things work with each other.

Here we first clarify our prerequisites. The object has at least one synchronized method, otherwise this key has no meaning. Of course, there will be no such theme of ours.

A person wanted to enter a locked room. He came to the door of the house and saw the key there (indicating that no one else wanted to use the locked room yet). So he walked up, got the keys

, and used the rooms according to his plan. Note that he returns the key immediately after each use of the locked room. Even if he wants to use two locked rooms in a row, he has to return the key and get it back in the middle.

Therefore, the principle of using keys under normal circumstances is: "Borrow as you use, return as soon as you use it."

At this time, other people can use the unlocked rooms without restrictions, and one person can use one room , two people can use one room, there is no limit. But if someone wants to enter a locked room, he has to run to the door to see it. If you have the key, of course you can take it and leave. If you don't have the key, you can only 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, if there are other people waiting for the key when he returns the key, there is no guarantee that this guy can get it again. (The JAVA specification clearly states in many places that there are no guarantees. For example, how long will

Thread.sleep() return to running after a break? Which thread with the same priority will be executed first? When the lock to access the object is released, it will be in the waiting pool. Which of the multiple threads will get priority, etc. I think the final decision lies with the JVM. The reason why there is no guarantee is because when the JVM makes the above decision, it does not simply make it based on one condition. The judgment is based on many conditions. If there are too many judgment conditions, it may affect the promotion of JAVA. It may also be due to intellectual property protection reasons and it will be ignored.

. It’s understandable. But I believe that these uncertainties are not completely uncertain, because even the seemingly random phenomena can be found by anyone who has studied computers. As you know, the scientific name for random numbers in computers is pseudo-random numbers, which are written by people using a certain method. They just look random. In addition, it may be because it is too troublesome and meaningless to determine. I’m not sure yet.)

Let’s take a look at the synchronization code block. It is slightly different from the synchronization method.

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

2. The synchronization code block can also manually specify the key of another object. Just like specifying which key can be used to open the lock of this screen, you can use the key of this house; you can also specify

to use the key of another house to open it. In this case, you have to run to another house Get that key there and use that house key to open the locked screen of this house.

                                                                                                                                                                                                                               Remember that the key of the other house that you have obtained will not prevent others from entering the unlocked room of that house.

                                                                                                                          Why use synchronized code blocks? I think it should be like this: First of all, the synchronization part of the program affects the operating efficiency, and a method usually creates some local variables first, and then performs some operations on these variables, such as calculations, display, etc.; and The more code covered by synchronization, the more severe the impact on efficiency. So we usually try to keep its scope of impact as small as possible.

How to do it? Synchronized code blocks. We only synchronize the parts of a method that should be synchronized, such as operations.

码 In addition, synchronous code blocks can specify the characteristics of the key to have an additional benefit, which is the key that can occupy a certain object within a certain period of time. Do you still remember the principles of using keys under normal circumstances? These are no ordinary circumstances. The key you obtain is not returned forever, but is returned when you exit the synchronized code block.连 Use the guy who wants to use two locking rooms in a row for an example. How can I continue to use another room after using one room? Use synchronized code blocks. First create another thread, make a synchronization code block, and point the lock of that code block to the key of the house. Then start that thread. As long as you can grab the key to this house

when you enter that code block, you can keep it until you exit that code block. In other words, you can even traverse all the locked rooms in this room, and even sleep (10*60*1000), but there are still

1000 threads waiting for the key at the door. It's quite enjoyable. P Let's talk about the correlation between the Sleep () method and the key. If a thread is forced to sleep() after getting the key and has not completed the synchronization content, the key will still be there. The key will not be returned until it is run again and all synchronization content is completed. Remember, the guy just got tired from working and went to take a rest. He didn't finish what he wanted to do. In order to prevent others from entering the room and making a mess inside, he had to wear the only key even when sleeping.

Finally, some people may ask, why do we need one key to open the door instead of one key for each door? I think this is purely a matter of complexity. One key for one door is certainly more secure, but it will involve a lot of problems. The generation, storage, acquisition, return of keys, etc. Its complexity may increase geometrically as the number of synchronization methods increases, seriously affecting efficiency. This can be regarded as a matter of trade-off. How undesirable it is to greatly reduce efficiency in order to increase a little bit of security.

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, To create a time difference, which is the opportunity for errors, Thread.sleep(10) is used


Java's multi-thread support and synchronization mechanism are loved by everyone. It seems that using the synchronized keyword can easily solve multi-threading Shared data synchronization problem. What is it like

? ——It is necessary to have an in-depth understanding of the role of the synchronized keyword before we can make a conclusion.


In general, the synchronized keyword can be used as a modifier of a function, or as a statement within a function, which is what we usually call synchronization methods and synchronization statement blocks. If classified further,

synchronized can act on instance variables, object references, static functions and class literals (class name literals).

Before further elaboration, we need to clarify a few points:

A. Regardless of 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 a function as a lock - and the synchronized method is likely to be accessed by objects in other threads.

B. Each object has only one lock associated with it.

C. Achieving synchronization requires a lot of system overhead and may even cause deadlock, so try to avoid unnecessary synchronization control.

Next, let’s discuss the impact of synchronized in different places on the code:

Assume that P1 and P2 are different objects of the same class. This class defines synchronization blocks or synchronization methods in the following situations. P1 and P2 are They can all be called.

1. When using synchronized as a function modifier, the sample code is as follows:

Public synchronized void methodAAA()

{

//….

}

This is the synchronization method, so which object is synchronized locked at this time? What it locks is the object that calls this synchronized method. In other words, when an object P1 executes this synchronization method in different threads, they will form mutual exclusion to achieve a synchronization effect. However, another object P2 generated by the Class to which this object belongs can arbitrarily call this method with the

synchronized keyword added.

The sample code above is equivalent to the following code:

public void methodAAA()

{

synchronized (this) // (1)

{

//…..

}

}

What does this in (1) refer to? 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 the object reference. ——Only the thread that has obtained the P1 object lock can call the synchronization method of P1. As far as P2 is concerned, the P1 lock has nothing to do with it. The program may also get rid of the control of the synchronization mechanism in this situation. Causing data chaos: (

2. Synchronization block, the sample code is as follows:

public void method3(SomeObject so)

{

synchronized(so)

{

//…..

}

}

At this time, the lock is the so object. Whoever gets the lock can run the code controlled by it. When there is a clear object as the lock, you can write the program like this, but when there is no clear object.
The exact object acts as a lock. When you just want to synchronize a piece of code, you can create a special instance variable (it must be an object) to act as a lock:

class Foo implements Runnable

{

      private byte[] lock = new byte[0]; // Special instance variable

                                                                        use using using ‐                     through using ’ through ’ s ’ through using using using ’s ’ through ’s ’ through ‐ to ‐ ‐‐‐‐ } new byte[0];                                                              

Note: Zero A length byte array object will be more economical to create than any object - look at the compiled bytecode: generating a zero-length byte[] object requires only 3 opcodes, while Object lock

= new Object() requires 7 lines of operation code.

3. Apply synchronized to static function, the sample code is as follows:


Class Foo

{

     public synchronized static void methodAAA()                                                                       V Public void methodbbbb () {

Synchronized (foo.class) // Class Literal It has the same effect as the synchronized static function. The lock obtained is very special. It is the class (Class) to which the object currently calling this method belongs, rather than a specific object generated by this Class. .

I remember reading in the book "Effective Java" that using Foo.class and P1.getClass() for synchronization locks is not the same. You cannot use P1.getClass() to achieve the purpose of locking this Class. . P1 refers to the object generated by class Foo.

It can be inferred: If a synchronized static function A is defined in a class, and a synchronized instance function B is also defined, then the same object Obj of this class will access the A and B methods respectively in multiple threads. , will not constitute synchronization because their locks are different. The lock of method A is the object Obj, and the lock of method B is the Class to which Obj belongs.

The summary is as follows:

Understanding which object is locked by synchronized can help us design safer multi-threaded programs.

There are also some techniques that can make our synchronous access to shared resources more secure:


1. Define the private instance variable + its get method instead of the public/protected instance variable. If the variable is defined as public, the object can be obtained directly from the outside world and change it, bypassing the control of the synchronization method. This is also one of the standard implementation methods of JavaBean.

2. If the instance variable is an object, such as an array or ArrayList, then the above method is still unsafe, because when the external object gets the reference of the instance object through the get method and points it to another object, then this private The variables have also changed, which is very dangerous. At this time, you need to add synchronized synchronization to the get method, and only return the clone() of this private object - in this way, what the caller gets is a reference to the object copy


Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Top 4 JavaScript Frameworks in 2025: React, Angular, Vue, Svelte Top 4 JavaScript Frameworks in 2025: React, Angular, Vue, Svelte Mar 07, 2025 pm 06:09 PM

This article analyzes the top four JavaScript frameworks (React, Angular, Vue, Svelte) in 2025, comparing their performance, scalability, and future prospects. While all remain dominant due to strong communities and ecosystems, their relative popul

How do I implement multi-level caching in Java applications using libraries like Caffeine or Guava Cache? How do I implement multi-level caching in Java applications using libraries like Caffeine or Guava Cache? Mar 17, 2025 pm 05:44 PM

The article discusses implementing multi-level caching in Java using Caffeine and Guava Cache to enhance application performance. It covers setup, integration, and performance benefits, along with configuration and eviction policy management best pra

How does Java's classloading mechanism work, including different classloaders and their delegation models? How does Java's classloading mechanism work, including different classloaders and their delegation models? Mar 17, 2025 pm 05:35 PM

Java's classloading involves loading, linking, and initializing classes using a hierarchical system with Bootstrap, Extension, and Application classloaders. The parent delegation model ensures core classes are loaded first, affecting custom class loa

Spring Boot SnakeYAML 2.0 CVE-2022-1471 Issue Fixed Spring Boot SnakeYAML 2.0 CVE-2022-1471 Issue Fixed Mar 07, 2025 pm 05:52 PM

This article addresses the CVE-2022-1471 vulnerability in SnakeYAML, a critical flaw allowing remote code execution. It details how upgrading Spring Boot applications to SnakeYAML 1.33 or later mitigates this risk, emphasizing that dependency updat

Node.js 20: Key Performance Boosts and New Features Node.js 20: Key Performance Boosts and New Features Mar 07, 2025 pm 06:12 PM

Node.js 20 significantly enhances performance via V8 engine improvements, notably faster garbage collection and I/O. New features include better WebAssembly support and refined debugging tools, boosting developer productivity and application speed.

Iceberg: The Future of Data Lake Tables Iceberg: The Future of Data Lake Tables Mar 07, 2025 pm 06:31 PM

Iceberg, an open table format for large analytical datasets, improves data lake performance and scalability. It addresses limitations of Parquet/ORC through internal metadata management, enabling efficient schema evolution, time travel, concurrent w

How can I implement functional programming techniques in Java? How can I implement functional programming techniques in Java? Mar 11, 2025 pm 05:51 PM

This article explores integrating functional programming into Java using lambda expressions, Streams API, method references, and Optional. It highlights benefits like improved code readability and maintainability through conciseness and immutability

How to Share Data Between Steps in Cucumber How to Share Data Between Steps in Cucumber Mar 07, 2025 pm 05:55 PM

This article explores methods for sharing data between Cucumber steps, comparing scenario context, global variables, argument passing, and data structures. It emphasizes best practices for maintainability, including concise context use, descriptive

See all articles