Summarized some of the characteristics of synchronized, the shortcomings hope to point out.
The basic characteristics of synchronized:
1, synchronized lock reentry
Explanation: Reentrant, literally, this lock can be acquired twice. That is, when a thread acquires the lock of object A, then during the execution of its code (the lock of object A is not released), it can request the lock of object A again, and can obtain the lock of object A again, instead of having a deadlock problem. The keyword synchronized has this feature and is a reentrant lock.
code show as below:
public class SynchronizedDemo {
public synchronized void method1(){
System.out.println("method1");
mothed2();
}
public synchronized void method2(){
System.out.println("method2");
}
public static void main(String...args){
final SynchronizedDemo synchronizedDemo = new SynchronizedDemo();
new Thread(new Runnable() {
@Override
public void run() {
synchronizedDemo.method1();
}
}).start();
}
}
Output result:
method1;
method2;
It can be seen from the output that the created thread acquired the synchronizedDemo object's lock twice, verifying that synchronized is a reentrant lock.
What is the significance of introducing reentrant locks?
You can acquire your own internal lock. This avoids a deadlock when the same object lock is called a second time.
In actual development, the order modification and order verification (inventory verification, etc.) should be added with synchronized locks; when you make order modifications, you need to do order verification first, (obtain the order object lock twice) so that the reentrant lock . and many more.
Other properties of reentrant locks-father-son inheritance
code show as below:
public class SynchronizedDome1 {
public synchronized void method1() {
System.out.println("method1");
}
static class SynchronizedDemo2 extends SynchronizedDome1{
public synchronized void method2() {
System.out.println("method2");
method1();
}
}
public static void main(String...args){
final SynchronizedDemo2 synchronizedDemo2 = new SynchronizedDemo2();
new Thread(new Runnable() {
@Override
public void run() {
synchronizedDemo2.method2();
}
}).start();
}
}
Output result:
method2;
method1;
It means that you can reenter the parent object lock after acquiring the child object lock.
2. After an exception occurs, the lock is automatically released.
code show as below:
public class SynchronizedDome2 {
public int i = 10;
public String str;
public synchronized void method1() {
for(;i>0;i--){
System.out.println("i:"+i);
if(i==3){
str.toCharArray();
}
}
}
public static void main(String...args){
final SynchronizedDemo2 synchronizedDemo2 = new SynchronizedDemo2();
new Thread(new Runnable() {
@Override
public void run() {
synchronizedDemo2.method1();
}
}).start();
}
}
Output result:
i:9
i:8
i:7
i:6
i:5
i:4
i:3
java.lang.NullPointerException
at thread.SynchronizedDome2.method1(SynchronizedDome2.java:10)
at thread.SynchronizedDome2$1.run(SynchronizedDome2.java:19)
at java.lang.Thread.run(Thread.java:745)
It indicates that when an exception occurs, the program does not continue to run, and the object lock is released.
3. Use the object as a listener.
public class SynchronizedDome3 {
public String str = "lock";
public void method1() {
synchronized (str){
System.out.println("当前线程名:"+Thread.currentThread().getName());
}
}
public static void main(String...args){
final SynchronizedDemo3 synchronizedDemo3 = new SynchronizedDemo3();
new Thread(new Runnable() {
@Override
public void run() {
synchronizedDemo3.method1();
}
},"name1").start();
new Thread(new Runnable() {
@Override
public void run() {
synchronizedDemo3.method1();
}
},"name2").start();
}
}
当前线程名:name2
当前线程名:name1
或者
当前线程名:name1
当前线程名:name2
说明: 选取任意对象作为锁
4,单例模式---双重校验锁(懒汉式)
public class SingleCase {
private static SingleCase instance2;
public static SingleCase getInstance2(){
if(instance2 == null){
synchronized(SingleCase.lass){
if(instance2 == null){
instance2 = new SingleCase();
}
}
}
return instance2;
}
}