thread synchronized(this)

Synchronized(this) Summary
This article mainly discusses the following three issues:
1. The role of synchronzied
2. Synchronized syntax
3. Understanding of synchronized(this)

First , explain
the role of the synchronized function of the Synchronzied keyword. A word summary is: thread synchronization. It can be used to modify methods in an object and lock the object. It is equivalent to no matter which thread A runs to this method every time, it must check whether there is any other thread B (or CD, etc.) that is using this method, and if so, wait for thread B (or CD) that is using this method. After running this method, run this thread A, if not, run it directly.

Then, talk about synchronized syntax
Synchronzied keyword includes two usages: synchronized method and synchronized block.
1. Synchronized methods
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 obtain the lock of the class instance that calls the method to execute, otherwise the thread to which it belongs is blocked. The lock is not released until the method returns, after which the blocked thread can acquire the lock and re-enter the executable state. This mechanism ensures that for each class instance at the same time, at most one of its member functions declared as synchronized is in the executable state (because at most one can obtain the lock corresponding to the class instance), thus effectively avoiding class members Access violations for variables (as long as all methods that might access class member variables are declared synchronized). In Java, not only a class instance, but also a lock for each class, 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.
2. synchronized block The
synchronized method locks the entire method. Declaring a large method as synchronized will greatly affect efficiency. Typically, if the method run() of a thread class is declared as synchronized, since it is running for the entire life of the thread, it will cause it to affect the class. Invocation of any synchronized method will never succeed. Of course, we can solve this problem by putting the code that accesses the class member variables into a special method, declaring it as synchronized, and calling it in the main method, but Java provides us with a better solution, that is synchronized block.
Such as: synchronized(syncObject) {
  //Code that allows access control
  }
A synchronized block is a block of code in which the code must acquire a lock on the object syncObject (which can be a class instance or a class, as mentioned earlier) before it can execute, as described above. Since it can target any code block and can arbitrarily specify the locked object, it has high flexibility.

Finally, talk about synchronzied(this). The following examples are very clear, and only through demo can we understand the knowledge points more thoroughly. It is recommended to run it in the IDE and experience it yourself.
1. When two concurrent threads access the synchronized (this) synchronized 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 executing the 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, "A");
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) synchronized code block of an object, another thread can still access non-synchronized code blocks in the object. synchronized(this) synchronizes the block of code.



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



Third, it is especially critical that when a thread accesses a synchronized(this) synchronized code block of an object, Access by other threads to all other synchronized(this) synchronized code blocks in the object 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



Fourth, the third example is also applicable to other synchronous code blocks. That is, when a thread accesses an object's synchronized(this) synchronized code block, it acquires the object's object lock. As a result, other threads' access to all synchronized parts of the object object 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(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(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();
}
}



Result:

although the thread t1 acquires the object lock on Inner, but because thread t2 accesses the asynchronous 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 prepend Inner.m4t2() synchronized:



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 threads t1 and t2 access two unrelated parts of the same Inner object, because t1 acquires the object lock on Inner first, 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.m4t1()=0
t2 : Inner.m4t2 ()=4
t2 : Inner.m4t2()=3
t2 : Inner.m4t2()=2
t2 : Inner.m4t2()=1
t2 : Inner.m4t2()=0

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326594473&siteId=291194637