静态同步方法synchronized方法和synchronized(class)代码块
synchronized关键字嫁到static方法上的是给class类上锁,而synchronized加到非静态方法上是给对象上锁。
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();
}
}
输出结果
Thread-0
Thread-1
Thread-1b
Thread-0a
从输出结果可以看出两个方法的执行是异步执行的,异步执行的原因是一个是对象锁,一个是class类锁。 如果还是不理解,请看下面的方法。
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();
}
}
输出结果
Thread-0
Thread-0a
Thread-1
Thread-1b
一样是同步的,这就是类锁和对象锁的区别。
数据类型String的常量池特性
先看程序
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();
}
}
输出结果
a
a
a
a
a
a
...
不断的输出a,线程b根本没得到执行,这是为什么呢? 因为string的两个值都是AA,这就是因为string常量池带来的影响,AA在string常量池的缓存范围内,所以同步方法持有的是同一个对象,因此线程b得不到执行。
大多数情况下不能使用string对象作为锁对象,改用其他的,比如object对象。
其他常量池的情况也得小心,比如整形。
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());
}
}
输出结果
b
a
b
a
b
a
b
a
...