Understand the synchronized keyword in java

Source: Internet
Author: User

Understand the synchronized keyword in java:
--------------------------------------------------------------

In fact, more than 90% of my basic java knowledge comes from Thinking in Java. For the synchronized keyword,
At that time, I just browsed it. I probably knew what it meant and didn't take it into detail. This keyword has never been used.
Yesterday I saw Thinking in Patterns with the Observer mode in Java,
I read the source code of the Observable class and found that almost all the methods in it use the synchronized keyword (not all ),
Synchronized (this) {} blocks are used individually. So I found it necessary to understand this keyword.

I read the Thinking in Java second Chinese Version translated by Hou Jie again and got the following information about synchronized:

1. the synchronized keyword has two scopes:
1) In an object instance, synchronized aMethod () {} can prevent multiple threads from simultaneously accessing the object's synchronized method.
(If an object has multiple synchronized methods, as long as one thread accesses one of the synchronized methods, other threads do not
Can access any of the synchronized methods of this object at the same time ). At this time, the synchronized methods of different object instances are irrelevant.
That is to say, other threads can access the synchronized Method in another object instance of the same class at the same time;
2) is the scope of a class. synchronized static aStaticMethod {} prevents multiple threads from simultaneously accessing the synchronized static method in this class.
It can work on all object instances of the class.

2. In addition to using the synchronized keyword before the method, the synchronized keyword can also be used in a block in the method, indicating that only the resources in this block are mutually exclusive.
Usage: synchronized (this) {/* block */}. Its scope is the current object;

3. the synchronized keyword cannot be inherited. That is to say, the method of the base class synchronized f () {} is not automatically synchronized f () {} in the inheritance class (){},
Instead, it becomes f (){}. You need to explicitly specify a method of the inherited class as the synchronized method;

4. Questions:
I know that there is a static block (the loading time is not clear, so I need to learn it. It turns out Thinking in Java seems to be saying: the loading time of the static Block
It is an object instance of the class or a static method of the class is accessed, but this morning I read a statement on javaeye.com about when to execute the "<static block?
-The article "eway-JavaEye technology community>" is a bit confused later. :) maybe, you need to carefully learn the internal mechanism of JVM, which is the most fundamental way to understand such problems ),
There is also a synchronized block. Is there a synchronized static block? Is there a synchronized block in the class scope?

Today, I wrote the following example to verify whether there is a synchronized or synchronized static block in the above class range. The conclusion is that there is no such block. That is, for the entire
A resource within the scope of the class implements synchronized. the only method is to use the synchronized static method, like this: synchronized static void ff ()
{/* Your code here */} (after littlebat Note: 2007.2.13, with the help of a friend V.C, I finally know that a method of the class can exist within the entire class.
Synchronized block, like this: synchronized (TestSynchronized. class) {/* some code */}. For details, see later)

All examples are as follows. If I have any improper examples or ideas, I would like to give some advice. Thank you.

Routine: TestSynchronized. java
Public class TestSynchronized {
 
Static {
System. out. println ("Step 1: a static block in class scope .");
}

Static void f (){
System. out. println ("Step 2: a static method f () in class scope .");
}

Synchronized static void ff () {// The only way of synchronized a part in class scope.
System. out. println ("Step 3: a synchronized static method ff () in class scope .");
}

/* // No any synchronized block in class scope!
Synchronized {
System. out. println ("A synchronized block in class scope .");
}
*/

/* // No any synchronized static block in class scope!
Synchronized static {
System. out. println ("A synchronized static block in class scope .");
}
*/

Void fff (){
Synchronized (this ){
System. out. println ("Step 4: a synchronized block in method fff () in object scope .");
}
}

Synchronized void ffff (){
System. out. println ("Step 5: a synchronized method ffff () in object scope .");
}

Public static void main (String [] args ){

TestSynchronized. f ();
TestSynchronized. ff ();
(New TestSynchronized (). fff ();
(New TestSynchronized (). ffff ();

}

}

Running result:
Step 1: a static block in class scope.
Step 2: a static method f () in class scope.
Step 3: a synchronized static method ff () in class scope.
Step 4: a synchronized block in method fff () in object scope.
Step 5: a synchronized method ffff () in object scope.

The format below can implement synchronizing in Class scope:

Synchronized (TestSynchronized. Class ){
}


Yes, I can get synchronized block in a method in class scope
(Note: TestSynchronized. class isn't TestSynchronized. Class ):

Void fffff (){
Synchronized (TestSynchronized. class ){
System. out. println ("Step 6: a synchronized block in method fffff () in class scope .");
}
}

 
------------------------------------------------
Some Understanding of synchronized (this:
------------------------------------------------
The synchronized keyword, which has two usage methods: synchronized Method and synchronized block.
1. synchronized Method

The synchronized method is declared 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 this method before execution,
Otherwise, the thread to which the lock belongs is blocked. Once the method is executed, the lock is exclusive until it is returned from the method. After that, the blocked thread can obtain the lock and re-enter the executable state.
This mechanism ensures that at most one member function declared as synchronized for each class instance at the same time is executable (because at most one member function can
Obtain the lock corresponding to this type of instance), so as to effectively avoid access conflicts between class member variables (as long as all methods that may be used to declare class member variables are declared as synchronized ).
In Java, not only are class instances, but each class also corresponds to a lock. In this way, we can declare the static member functions of the class as synchronized to control its static member variables of the class.
Access.
Synchronized Method defects: If you declare a large method as synchronized, it will greatly affect the efficiency. Typically, if you declare the Thread class method run ()
Synchronized, because it has been running throughout the life cycle of the thread, it will cause its call to any synchronized Method of this class to never succeed. Of course we can.
By putting the code of member variables of the attention class into a special method, declaring it as synchronized and calling it in the main method to solve this problem, but Java provides us with better
The solution is the synchronized block.

2. synchronized Block

Use the synchronized keyword to declare the synchronized block. Syntax:
Synchronized (syncObject ){
// Code that allows access control
}
The synchronized block is a code block in which the Code must obtain the lock of the object syncObject (as described earlier, it can be a class instance or class) before execution. The specific mechanism is described earlier.
It is highly flexible because it can target any code block and can specify any locked object.


1. When two concurrent threads access the synchronized (this) synchronization code block of the same object, only one thread can be executed within a time period.
The other thread must wait until the current thread finishes executing this code block before executing this code block.

2. However, when a thread accesses a synchronized (this) Synchronous Code block of an object, the other thread can still access non-
Synchronized (this) synchronization code block.

3. When a thread accesses a synchronized (this) Synchronous Code block of the object, other threads
Access to the synchronized (this) synchronization code block will be blocked.

4. The third example also applies to other synchronous code blocks. That is, when a thread accesses a synchronized (this) Synchronous Code block of the object,
It obtains the object lock of this object. As a result, access by other threads to all the synchronized code parts of the object is temporarily blocked.

5. The above rules apply to other Object locks.

Example:

1. When two concurrent threads access the synchronized (this) synchronization code block of the same object, only one thread can be executed within a time period.
The other thread must wait until the current thread finishes executing this code block before executing this code block.
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, "");
Thread tb = new Thread (t1, "B ");
Ta. start ();
Tb. start ();
}
}

Result:

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) Synchronous Code block of an object, the other thread can still access non-
Synchronized (this) synchronization code block.

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

Result:

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

3. When a thread accesses a synchronized (this) Synchronous Code block of the object, other threads
Access to the synchronized (this) synchronization code block will be blocked.

// 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 (500 );
} Catch (InterruptedException ie ){
}
}
}

}

Result:

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

4. The third example also applies to other synchronous code blocks. That is, when a thread accesses a synchronized (this) Synchronous Code block of the object,
It obtains the object lock of this object. As a result, access by other threads to all the synchronized code parts of the object is temporarily blocked.

// Modify Thread2.m4t2 () as follows:

Public synchronized void m4t2 (){
Int I = 5;
While (I --> 0 ){
System. out. println (Thread. currentThread (). getName () + ":" + I );
Try {
Thread. sleep (500 );
} Catch (InterruptedException ie ){
}
}
}

Result:

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

5. The above rules 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) {// use the 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 ();
}
}

Result:

Although thread t1 acquires the object lock on the Inner, thread t2 accesses the non-synchronous part of the same Inner. Therefore, 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 (I --> 0 ){
System. out. println (Thread. currentThread (). getName () + ": Inner. m4t2 () =" + I );
Try {
Thread. sleep (500 );
} Catch (InterruptedException ie ){
}
}
}

Result:

Although thread t1 and t2 access two unrelated parts of the same Inner object, because t1 first obtains the object lock on Inner, so t2 has access to Inner. access to m4t2 () is also blocked because m4t2 () is a synchronous method in the 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

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.