synchronized 加到 static 方法前面是给class 加锁,即类锁;而synchronized 加到非静态方法前面是给对象上锁。这两者的区别我用代码来演示下:
1.类锁和对象锁是两把不同的锁,多线程执行两个不同锁的方法时是异步的
加锁的类(下面几个此类不变)
public class Task2 {
public synchronized static void doLongTimeTaskA() {
System.out.println("name = " + Thread.currentThread().getName() + ", begain");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("name = " + Thread.currentThread().getName() + ", end");
}
public synchronized static void doLongTimeTaskB() {
System.out.println("name = " + Thread.currentThread().getName() + ", begain");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("name = " + Thread.currentThread().getName() + ", end");
}
public synchronized void doLongTimeTaskC() {
System.out.println("name = " + Thread.currentThread().getName() + ", begain");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("name = " + Thread.currentThread().getName() + ", end");
}
}
多线程如下
class ThreadA extends Thread {
private Task2 mTask2;
public ThreadA(Task2 tk) {
mTask2 = tk;
}
public void run() {
mTask2.doLongTimeTaskA();
}
}
class ThreadB extends Thread {
private Task2 mTask2;
public ThreadB(Task2 tk) {
mTask2 = tk;
}
public void run() {
mTask2.doLongTimeTaskB();
}
}
class ThreadC extends Thread {
private Task2 mTask2;
public ThreadC(Task2 tk) {
mTask2 = tk;
}
public void run() {
mTask2.doLongTimeTaskC();
}
}
main函数如下
public static void main(String[] args) {
Task2 mTask2 = new Task2();
ThreadA ta = new ThreadA(mTask2);
ThreadB tb = new ThreadB(mTask2);
ThreadC tc = new ThreadC(mTask2);
ta.setName("A");
tb.setName("B");
tc.setName("C");
ta.start();
tb.start();
tc.start();
}
执行结果如下
name = A, begain
name = C, begain
name = C, end
name = A, end
name = B, begain
name = B, end
doLongTimeTaskA()和 doLongTimeTaskB()互斥,与doLongTimeTaskC()不互斥,类锁和对象锁是两类不同的锁
2,对象锁对同一个实列对象起作用,类锁对该类的所有实列对象起作用
加锁类不变,用上面的
多线程更改如下
class ThreadA extends Thread{
private Task2 mTask2;
public ThreadA(Task2 tk){
mTask2 = tk;
}
public void run() {
mTask2.doLongTimeTaskC();
}
}
class ThreadB extends Thread{
private Task2 mTask2;
public ThreadB(Task2 tk){
mTask2 = tk;
}
public void run() {
mTask2.doLongTimeTaskC();
}
}
main函数如下
public static void main(String[] args) {
Task2 mTaska = new Task2();
Task2 mTaskb = new Task2();
ThreadA ta = new ThreadA(mTaska );
ThreadB tb = new ThreadB(mTaskb );
ta.setName("A");
tb.setName("B");
ta.start();
tb.start();
}
运行结果如下
name = A, begain
name = B, begain
name = A, end
name = B, end
对象锁锁的对象不一样,分别是mTaska , mTaskb,所以线程A和线程B调用 doLongTimeTaskC 是异步执行的。
然后我们main函数不变,依旧是对两个实列而言 ,更改多线程的class走类锁,执行doLongTimeTaskA()或者doLongTimeTaskB()
更改后的多线程类如下
class ThreadA extends Thread{
private Task2 mTask2;
public ThreadA(Task2 tk){
mTask2 = tk;
}
public void run() {
mTask2.doLongTimeTaskA();
}
}
class ThreadB extends Thread{
private Task2 mTask2;
public ThreadB(Task2 tk){
mTask2 = tk;
}
public void run() {
mTask2.doLongTimeTaskB();
}
}
结果如下
name = A, begain
name = A, end
name = B, begain
name = B, end
可以看出 在线程A执行完doLongTimeTaskA方法后,线程B才会获得该类锁接着去执行doLongTimeTaskA。也就是说,类锁对所有的该类对象都能起作用。
结论:
1. 如果多线程同时访问同一类的 类锁(synchronized 修饰的静态方法)以及对象锁(synchronized 修饰的非静态方法)这两个方法执行是异步的,原因:类锁和对象锁是2种不同的锁。
2. 类锁对该类的所有对象都能起作用,而对象锁只对同一个实例对象起作用。