Static synchronization method synchronized method and synchronized(class) code block
The synchronized keyword is passed to the static method to lock the class, while the synchronized keyword is added to the non static method to lock the object.
public class MainClass { synchronized public void printStringA() { String a = Thread.currentThread().getName(); String b = Thread.currentThread().getName() + "a"; System.out.println(a); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(b); } synchronized public static void printStringB() { String a = Thread.currentThread().getName(); String b = Thread.currentThread().getName() + "b"; System.out.println(a); System.out.println(b); } } public class ThreadA extends Thread { private MainClass mainClass; public ThreadA(MainClass mainClass) { this.mainClass = mainClass; } @Override public void run() { mainClass.printStringA(); } } public class ThreadB extends Thread { private MainClass mainClass; public ThreadB(MainClass mainClass) { this.mainClass = mainClass; } @Override public void run() { mainClass.printStringB(); } } public class RunClass { public static void main(String[] args) throws InterruptedException { MainClass mainClass = new MainClass(); ThreadA threadA = new ThreadA(mainClass); threadA.start(); ThreadB threadB =new ThreadB(mainClass); threadB.start(); } }
Output result
Thread-0 Thread-1 Thread-1b Thread-0a
From the output results, we can see that the execution of the two methods is asynchronous. The reason for asynchronous execution is that one is object lock and the other is class lock. If you still don't understand, please look at the following methods.
public class MainClass { synchronized public static void printStringA() { String a = Thread.currentThread().getName(); String b = Thread.currentThread().getName() + "a"; System.out.println(a); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(b); } synchronized public static void printStringB() { String a = Thread.currentThread().getName(); String b = Thread.currentThread().getName() + "b"; System.out.println(a); System.out.println(b); } } public class RunClass { public static void main(String[] args) throws InterruptedException { MainClass mainClass = new MainClass(); MainClass mainClass2 = new MainClass(); ThreadA threadA = new ThreadA(mainClass); threadA.start(); Thread.sleep(100); ThreadB threadB =new ThreadB(mainClass2); threadB.start(); } }
Output result
Thread-0 Thread-0a Thread-1 Thread-1b
This is the difference between class lock and object lock.
Constant pool property of data type String
Look at the program first.
public class MainClass { public void printStringB(String stringParam) { try { synchronized (stringParam) { while (true) { System.out.println(Thread.currentThread().getName()); Thread.sleep(1000); } } } catch ( InterruptedException ex) { ex.printStackTrace(); } } } public class ThreadA extends Thread { private MainClass mainClass; public ThreadA(MainClass mainClass) { this.mainClass = mainClass; } @Override public void run() { mainClass.printStringB("AA"); } } public class ThreadB extends Thread { private MainClass mainClass; public ThreadB(MainClass mainClass) { this.mainClass = mainClass; } @Override public void run() { mainClass.printStringB("AA"); } } public class RunClass { public static void main(String[] args) throws InterruptedException { MainClass mainClass = new MainClass(); MainClass mainClass2 = new MainClass(); ThreadA threadA = new ThreadA(mainClass); threadA.setName("a"); threadA.start(); ThreadB threadB =new ThreadB(mainClass2); threadB.setName("b"); threadB.start(); } }
Output result
a a a a a a ...
Continuously output a, thread b has not been executed at all, why is this? Because both values of string are AA, which is the impact of string constant pool. AA is within the cache range of string constant pool, so the synchronization method holds the same object, so thread b cannot be executed.
In most cases, you can't use string objects as lock objects, but use other objects, such as object objects.
Other constant pools also need to be careful, such as shaping.
public class MainClass { public void printStringB(Object object) { try { synchronized (object) { while (true) { System.out.println(Thread.currentThread().getName()); Thread.sleep(1000); } } } catch ( InterruptedException ex) { ex.printStackTrace(); } } } public class ThreadA extends Thread { private MainClass mainClass; public ThreadA(MainClass mainClass) { this.mainClass = mainClass; } @Override public void run() { mainClass.printStringB(new Object()); } } public class ThreadB extends Thread { private MainClass mainClass; public ThreadB(MainClass mainClass) { this.mainClass = mainClass; } @Override public void run() { mainClass.printStringB(new Object()); } }
Output result
b a b a b a b a ...