一、Synchronized的作用
修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁
修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁
修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。
二、Synchronized使用方式
先看一下没有同步的情况
public class TestNoSynchronized {
public static void main(String[] args) {
TestNoSynchronized testNoSynchronized = new TestNoSynchronized();
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
testNoSynchronized.methodANoSynchronized();
}
});
threadA.start();
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
testNoSynchronized.methodBNoSynchronized();
}
});
threadB.start();
}
public void methodANoSynchronized(){
System.out.println(" I am methodANoSynchronized start");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" I am methodANoSynchronized end");
}
public void methodBNoSynchronized(){
System.out.println(" I am methodBNoSynchronized start");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" I am methodBNoSynchronized end");
}
}
运行结果如下:
I am methodANoSynchronized start
I am methodBNoSynchronized start
I am methodBNoSynchronized end
I am methodANoSynchronized end
两个线程异步执行,methodANoSynchronized 先执行,但是methodBNoSynchronized 先执行完。
1、修饰普通方法
public class TestSynchronized {
public static void main(String[] args) {
TestSynchronized testSynchronized = new TestSynchronized();
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
testSynchronized.methodASynchronized();
}
});
threadA.start();
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
testSynchronized.methodBSynchronized();
}
});
threadB.start();
}
public synchronized void methodASynchronized(){
System.out.println(" I am methodASynchronized start");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" I am methodASynchronized end");
}
public synchronized void methodBSynchronized(){
System.out.println(" I am methodBSynchronized start");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" I am methodBSynchronized end");
}
}
运行结果如下:
I am methodASynchronized start
I am methodASynchronized end
I am methodBSynchronized start
I am methodBSynchronized end
从运行结果可以看出,两个方法是同步执行的,即methodASynchronized 先执行且执行完毕后methodBSynchronized 才执行。给普通方法加synchronized,实质上同步的是对象,也就是说多个线程对同一个对象的同步方法的执行是线程安全的,即线程threadA 执行该对象同步方法时,其他线程无法执行该对象的任意一个同步方法。
2、修饰静态方法
public class TestStaticSynchronized {
public static void main(String[] args) {
TestStaticSynchronized staticSynchronized = new TestStaticSynchronized();
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
staticSynchronized.methodASynchronized();
}
});
threadA.start();
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
staticSynchronized.methodBSynchronized();
}
});
threadB.start();
Thread threadC = new Thread(new Runnable() {
@Override
public void run() {
TestStaticSynchronized.methodCSynchronized();
}
});
threadC.start();
}
public static synchronized void methodASynchronized(){
System.out.println(" I am methodASynchronized start");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" I am methodASynchronized end");
}
public static synchronized void methodBSynchronized(){
System.out.println(" I am methodBSynchronized start");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" I am methodBSynchronized end");
}
public static synchronized void methodCSynchronized(){
System.out.println(" I am methodCSynchronized start");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" I am methodCSynchronized end");
}
}
运行结果如下:
I am methodCSynchronized start
I am methodCSynchronized end
I am methodASynchronized start
I am methodASynchronized end
I am methodBSynchronized start
I am methodBSynchronized end
从运行结果可以看出,三个方法是同步执行的。synchronized关键字加在静态方法上,实质上同步的对象是这个类,包括这个类的所有实例以及这个类直接调用静态同步方法都必须是线程安全的,也就是说存在一个线程获得锁,正在通过该类的实例去执行静态同步方法或者直接通过类调用静态同步方法,其他线程都无法执行这个类实例的所有静态同步方法或者通过类调用静态同步方法。
3、修饰代码块
public class TestBlockSynchronized {
public static void main(String[] args) {
TestBlockSynchronized blockSynchronized = new TestBlockSynchronized();
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
blockSynchronized.methodABlock();
}
});
threadA.start();
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
blockSynchronized.methodBBlock();
}
});
threadB.start();
}
public void methodABlock(){
System.out.println(" I am methodABlock start");
try {
synchronized (this) {
System.out.println(" I am methodABlock");
Thread.sleep(3000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" I am methodABlock end");
}
public void methodBBlock(){
System.out.println(" I am methodBBlock start");
try {
synchronized (this) {
System.out.println(" I am methodBBlock");
Thread.sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" I am methodBBlock end");
}
}
运行结果如下:
I am methodABlock start
I am methodABlock
I am methodBBlock start
I am methodABlock end
I am methodBBlock
I am methodBBlock end
从运行结果可以看出,两个线程在不同的时机进入了不同的方法,但是当执行到代码块的时候,methodBBlock 的代码块等待methodABlock 方法全部执行完毕才执行。