Java synchronized usage detailed _java

Source: Internet
Author: User
Tags modifier object object sleep thread class

A keyword in the Java language that, when used to modify a method or a block of code, ensures that at most one thread at the same time executes that segment of code.

First, when two concurrent threads access the synchronized (this) synchronized code block in the same object objects, only one thread can be executed at a time. Another thread must wait until the current thread finishes executing the code block before executing the code block.

Second, however, when a thread accesses a synchronized (this) synchronization code block of object, another thread can still access a non-synchronized (this) synchronized code block in that object.

Third, it is particularly critical that when a thread accesses a synchronized (this) synchronization code block of object, access to all other synchronized (this) synchronized code blocks in object is blocked by other threads.

The third example also applies to other synchronized code blocks. That is, when a thread accesses a synchronized (this) synchronization code block of object, it obtains the object lock of the objects. As a result, access to all of the synchronization code portions of the object object by other threads is temporarily blocked.

The above rules apply to other object locks as well.

An example is provided:

First, when two concurrent threads access the synchronized (this) synchronized code block in the same object objects, only one thread can be executed at a time. Another thread must wait until the current thread finishes executing the code block before executing the code block.

package ths;

public class Thread1 implements Runnable {public 
   void run () { 
     synchronized (.) {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 (); 
   } 


Results:

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

Second, however, when a thread accesses a synchronized (this) synchronization code block of object, another thread can still access a non-synchronized (this) synchronized code block in that object.

 package ths; 
        public class Thread2 {public void m4t1 () {synchronized () {int i = 5; 
          while (i--> 0) {System.out.println (Thread.CurrentThread (). GetName () + ":" + i); 
          try {thread.sleep (500); 
     The catch (Interruptedexception IE) {}}} is 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 thre 
     Ad2 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 particularly critical that when a thread accesses a synchronized (this) synchronization code block of object, access to all other synchronized (this) synchronized code blocks in object is blocked by other threads.

  Modify the Thread2.m4t2 () method: public 
   void M4t2 () { 
     synchronized (this) { 
        int i = 5; 
        while (i--> 0) { 
          System.out.println (Thread.CurrentThread (). GetName () + ":" + i); 
          try { 
             thread.sleep; 
          } catch (Interruptedexception IE) { 
          }

   }}

Results:

T1:4
T1:3
T1:2
T1:1
t1:0
T2:4
T2:3
T2:2
T2:1
t2:0

The third example also applies to other synchronized code blocks. That is, when a thread accesses a synchronized (this) synchronization code block of object, it obtains the object lock of the objects. As a result, access to all of the synchronization code portions of the object object by other threads is temporarily blocked.

 Modify the Thread2.m4t2 () method as follows: public

   synchronized void M4t2 () { 
     int i = 5; 
     while (i--> 0) { 
        System.out.println (Thread.CurrentThread (). GetName () + ":" + i); 
        try { 
          thread.sleep; 
        } catch (Interruptedexception IE) { 
        } 
   }}

Results:

T1:4
T1:3
T1:2
T1:1
t1:0
T2:4
T2:3
T2:2
T2:1
t2:0

The above rules apply to other object locks as well:

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); The catch (Interruptedexception IE) {}}} is private void M4t1 (Inner Inner) {SYNCHR 
   Onized (inner) {//Use Object lock 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 obtains an object lock on inner, thread T2 accesses the asynchronous part of the same inner. So 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 precede inner.m4t2 () with synchronized:

 Private synchronized void M4t2 () { 
     int i = 5; 
     while (i--> 0) { 
        System.out.println (Thread.CurrentThread (). GetName () + ": inner.m4t2 () =" + i); 
        try { 
          thread.sleep; 
        } catch (Interruptedexception IE) { 
        } 
   }}

Results:

Although thread T1 and T2 access two unrelated parts of the same inner object, inner's access to T2 () is blocked because T1 first obtains an object lock on Inner.m4t2, because M4t2 () is a synchronous 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

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. Such as:

 
 

The Synchronized method Controls access to class member variables: Each class instance corresponds to a lock, each synchronized method must obtain a lock that invokes the class instance of the method to execute, otherwise the owning thread is blocked, and once the method is executed, the lock is exclusive until the lock is released when the method returns , the blocked thread can then get the lock and re-enter the executable state. This mechanism ensures that at the same time for each class instance, at most only one of the member functions declared as synchronized is in the executable state (since at most one can obtain the lock of that class instance), This effectively avoids the access violation of class member variables (as long as all possible methods of accessing class member variables are declared as synchronized).

In Java, not just the class instance, each class also corresponds to a lock, so we can also declare the static member function of the class as synchronized to control its access to the static member variables of the class.

The flaw of the Synchronized method: If a large method is declared as synchronized, it will greatly affect efficiency, typically, if the thread class method run () is declared as synchronized, because it is running throughout its lifetime, Therefore, the invocation of any synchronized method in this class will never succeed. Of course, we can do this by putting the code that accesses the class member variable into a specialized method, declaring it as synchronized, and tuning it in the main method to solve the problem, but Java provides us with a better solution, which is the synchronized block.

2. Synchronized BLOCK: Declare synchronized block by 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 obtain the lock of the object SyncObject (as described previously, can be a class instance or Class), and the specific mechanism is described in the previous instance. Because you can target arbitrary blocks of code, and can arbitrarily specify locked objects, so flexibility is high.

Some understanding of the synchronized (this)
First, when two concurrent threads access the synchronized (this) synchronized code block in the same object objects, only one thread can be executed at a time. Another thread must wait until the current thread finishes executing the code block before executing the code block.

Second, however, when a thread accesses a synchronized (this) synchronization code block of object, another thread can still access a non-synchronized (this) synchronized code block in that object.

Third, it is particularly critical that when a thread accesses a synchronized (this) synchronization code block of object, access to all other synchronized (this) synchronized code blocks in object is blocked by other threads.

The third example also applies to other synchronized code blocks. That is, when a thread accesses a synchronized (this) synchronization code block of object, it obtains the object lock of the objects. As a result, access to all of the synchronization code portions of the object object by other threads is temporarily blocked.

The above rules are also applicable to other object locks.

Synchronized usage in Java

For example, an object is like a big house, and the door opens forever. There are a lot of rooms in the house (ie method).

These rooms have a locked (synchronized method) and are not locked (common method). A key was placed at the door of the room, and the key opened all the locked rooms.

In addition, I compare all the threads that want to call the object method to the person who chengxiang into a room in the house. So much for everything, so let's look at how these things work.

Here we begin by clarifying our prerequisites. The object has at least one synchronized method, otherwise the key has no meaning. Of course, we will not have this subject.

A man wanted to enter a locked room, and he came to the door of the house and saw the key there (indicating that no one else had to use the locked room for the time being). So he went up to get the keys and used the rooms according to his plan. Note that he will return the key once every time he uses a locked room. Even if he had to use two locked rooms in a row, he would return the keys in the middle. Therefore, the general principle of the use of the key is: "With the use of borrowed, the use of that is also." ”

At this time other people can unrestricted use of those unlocked rooms, one can use one, two people can use a room, there is no limit. But if someone wants to go into a locked room, he's going to go to the gate and look at it. Have the key of course take to go, no words, can only wait. If a lot of people are waiting for this key, who will give priority to the key when the key is returned? Not guaranteed. As in the previous example, the guy who wants to use two locked rooms in a row, if there are other people waiting for the key when the key is still in the middle, there is no guarantee that this guy will get it again. (The Java specification makes it clear in many places that it is not guaranteed that, like the Thread.Sleep (), how long it will return to run, the same priority thread is executed first, and that the number of threads in the waiting pool after the lock of the object is released is given priority, and so on.) I think the final decision is in the JVM, the reason is not guaranteed, because the JVM in making the decision, it is not simply based on a condition to make judgments, but according to a number of bars.

But because the judgment condition is too many, if said that may affect the Java promotion, may also be because of the intellectual property protection reason. Sun gave a no guarantee and mixed it up. Understandable. But I believe these uncertainties are not entirely uncertain. Because the computer itself is running according to the instructions. Even seemingly random phenomena, in fact, there are rules to find. The computer has learned that the scientific name of random numbers in the computer is a pseudo random number, is the use of a certain method of writing out, looks random. In addition, perhaps because to make the determination too laborious, also does not have much significance, therefore is uncertain is uncertain. )

Take a look at the sync code block again. and synchronized methods are a little different.

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

2. The synchronized code block can also be artificially specified to obtain key for some other object. It's like specifying which key to use to unlock this screen, you can use the key of the room, you can also specify the key to another house to open, so you have to run to another house to bring the key, and the house with the key to open the house with the lock of the screen.

Remember that the key to the other house that you obtained does not affect others entering the room without locks.

Why should I use a synchronized code block? I think it should be like this: the first part of the synchronization of the program is very affecting the efficiency of the operation, and a method is usually to create some local variables, and then do some operations on these variables, such as operations, display and so on, and the more code covered by synchronization, the greater the impact on efficiency. So we usually try to narrow the scope of the impact.

How to do it? Synchronize code blocks. We only synchronize where the synchronization is in one method, such as an operation.

In addition, the synchronization code block can specify the key the feature has an additional advantage, is the key that can occupy an object for a certain period of time. Do you remember the principle of using the key in general situation? It's not a normal situation now. The key you have achieved is not never return, but it is only when you exit the Sync code block.

and use the front guy who wants to use two locked rooms in a row for a metaphor. How to use the other one after using one of the rooms. Use the Sync code block. First create another thread, make a sync code block, and point the lock of that code block to the key of the house. And 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 code block. That is to say, you can even go through all the locked rooms in the room, even sleep (10*60*1000), and the door has 1000 lines thread and so on this key. Very enjoyable.

Here is a talk about the relationship between sleep () method and key. When a thread gets the key and does not complete the synchronized content, if it is forced to sleep (), the key is still there. The key will not be returned until it is run again and all the synchronized content is finished. Remember, the guy just got tired of working and went to take a break, and he didn't finish what he was going to do. In order to avoid other people into the room to make a mess in the inside, even in bed when he would have to put the only key on the body.

Finally, one might ask, why should a key be opened, not a key, a door? I think it's purely a matter of complexity. A key a door is safer, but it involves a lot of problems. The creation, custody, acquisition, restitution, etc. of the key. Its complexity may increase exponentially with the increase of synchronization method, which seriously affects the efficiency. That's a trade-off. In order to add a little bit of security, resulting in a much lower efficiency, is how undesirable ah.

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 =; 
String str = new string ();

public void Run () { 
  synchronized (str) {while 
  (num > 0) {

   try { 
   thread.sleep (1); 
   } catch (exc Eption e) { 
   e.getmessage (); 
   } 
   System.out.println (Thread.CurrentThread (). GetName () 
    + "This is" + num--);}}} 


In the example above, in order to create a time difference, which is the chance of error, the use of Thread.Sleep (10)

Java support for multithreading and synchronization mechanism by popular, it seems that the use of the Synchronized keyword can easily solve the problem of multithreading shared data synchronization. What's going on? --also have to synchronized the role of the key words to understand the conclusion.

In general, the Synchronized keyword can be used as a modifier of a function, or as a statement within a function, which is usually a synchronized method and a block of synchronized statements. In the finer categories, synchronized can be used for instance variables, object reference (reference), static functions, and class literals (class name literal constants).

Before we further elaborate, we need to be clear on a few points:

A Whether the Synchronized keyword is added to a method or an object, the lock it obtains is an object rather than a piece of code or function as a lock-and the synchronization method is likely to be

Object access to his thread.

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

C To achieve synchronization is a very large system overhead as a cost, and may even cause deadlock, so try to avoid unnecessary synchronization control.

Next, discuss synchronized's impact on the code in different places:

Assuming that P1, P2 are different objects of the same class, this class defines synchronization blocks or synchronization methods that can be invoked by P1, P2, and so on.

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

Public synchronized void Methodaaa ()

{

//...

}

This is also the synchronization method, then synchronized locked is what object? It locks a call to this synchronization method object. That is, when an object P1 the synchronization method in a different thread, they form a mutex that achieves the effect of synchronization. But another object generated by the class that this object belongs to P2 can invoke the method that was added to the Synchronized keyword arbitrarily.

The example code above is equivalent to the following code:

public void Methodaaa ()

{

synchronized (this)   //(1)

{

    //...

}

}}

(1) What does this refer to? It refers to the object that invokes this method, such as P1. The visible synchronization method is essentially a synchronized action on the object reference. -The thread that gets the lock on the P1 object can invoke the P1 synchronization method, and for P2, P1 the lock has nothing to do with it, and the program may get rid of the synchronization mechanism in this case, resulting in data chaos: (

2. Sync block, sample code as follows:

public void method3 (Someobject i)

{

  synchronized (so)

  { 
    //... 
  }

}}

Then the lock is the object of so, and whoever gets the lock can run the code it controls. When there is a clear object as a lock, you can write the program, but when there is no clear object as a lock and just want to synchronize a piece of code, you can create a special instance variable (it 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: A 0-length byte array object will be more economical than any object--view compiled bytecode: A 0-length byte[] object requires only 3 opcode, while the object lock= new Object () takes 7 lines of opcode.

3. The synchronized is applied to the static function, and 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 is to use class literal as a lock, and it produces the same effect as the synchronized static function, and the lock is special, the class that the object that is currently calling the method belongs to (class, Instead of being a specific object generated by this class.

Remember in the book "Effective Java" that the Foo.class and P1.getclass () used as a synchronous lock is not the same, can not use P1.getclass () to achieve the purpose of locking this class. P1 refers to objects that are generated by the Foo class.

It can be inferred that if a class has defined a synchronized static function A and also defines a synchronized instance function B, then the same object obj of this class will not constitute a synchronization when accessing A and B two methods, respectively, in multiple threads. Because their locks are not the same. The lock of a method is the object of obj, and the lock of B is the class that obj belongs to.

The summary is as follows:

Figuring out which object the synchronized is locking can help us design more secure multithreaded programs. There are also some techniques that make it more secure to synchronize access to shared resources:

1. Define private instance variable + its get method instead of defining public/protected instance variables. If you define a variable as public, the object can get it directly and change it in the outside world by bypassing the control of the synchronization method. This is also one of the standard implementations of JavaBean.

2. If the instance variable is an object, such as an array or ArrayList, the above method is still unsafe, because when an external object gets a reference to the instance object through the Get method and points it to another object, the private variable is changed, It's dangerous. At this point you need to synchronize the Get method with synchronized, and return only the Clone () of the private object--so that the caller gets a reference to the object's copy.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.