用法
- 用在 非静态方法 上(执行该方法的时候,对这个对象进行加锁)
- 用在 静态方法 上(执行该方法的时候,对整个类进行加锁)
- 在 代码块 中对某个对象加锁(在执行该代码块的时候,对该对象进行加锁)
- 在 代码块 中对某个类进行加锁(在执行该代码块的时候,对该类进行加锁)
1. 用在非静态方法上
public class TestThread {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
Thread thread = new Thread(new ThreadTest());
service.submit(thread);
service.submit(thread);
service.shutdown();
}
}
public class ThreadTest implements Runnable {
public synchronized void run() {
System.out.println("Start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("End");
}
}
输出结果:
Start
End
Start
End
可以看到,synchronized作用于非静态方法上,实际上是对对象加锁,对于同一对象,执行是同步的,而如果两个线程属于不同对象,则会导致这个锁失效:
public class TestThread {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
Thread thread1 = new Thread(new ThreadTest());
Thread thread2 = new Thread(new ThreadTest());
service.submit(thread1);
service.submit(thread2);
service.shutdown();
}
}
public class TestThread {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
Thread thread1 = new Thread(new ThreadTest());
Thread thread2 = new Thread(new ThreadTest());
service.submit(thread1);
service.submit(thread2);
service.shutdown();
}
}
输出结果:
Start
Start
End
End
对于不同的对象,执行的过程不是同步的,可知synchronized用在非静态方法上,是对这个对象加锁
2. 用在静态方法上
public class TestThread {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
Thread thread1 = new Thread(new ThreadTest());
Thread thread2 = new Thread(new ThreadTest());
service.submit(thread1);
service.submit(thread2);
service.shutdown();
}
}
public class ThreadTest implements Runnable {
public void run() {
Test.print();
}
}
public class Test {
public synchronized static void print() {
System.out.println("Start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("End");
}
}
输出结果:
Start
End
Start
End
静态方法是属于类的属性,存放在方法区中,与实例对象无关,所以 synchronized 用在静态方法上实际上是对整个类加锁,所以就算是不同实例,结果也是同步的,如果是同一类同一对象,也是一样的结果
3. 在代码块中对类进行加锁
public class TestThread {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
Thread thread = new Thread(new ThreadTest());
service.submit(thread);
service.submit(thread);
service.shutdown();
}
}
public class ThreadTest implements Runnable {
public void run() {
synchronized (ThreadTest.class) {
System.out.println("Start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("End");
}
}
}
输出结果:
Start
End
Start
End
对class类进行加锁,跟作用在静态方法上效果是相同的,只针对类,而不是针对具体对象
4. 在代码块中对对象进行加锁
public class TestThread {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
Thread thread = new Thread(new ThreadTest(new Test()));
service.submit(thread);
service.submit(thread);
service.shutdown();
}
}
public class ThreadTest implements Runnable {
private final Test test;
public ThreadTest(Test test) {
this.test = test;
}
public void run() {
synchronized (test) {
test.print();
}
}
}
public class Test {
public void print() {
System.out.println("Start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("End");
}
}
输出结果:
Start
End
Start
End
在run方法中,对Test对象进行了加锁,所以对相同对象执行方法是同步的,下面改写成两个不同对象:
public class TestThread {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
Thread thread1 = new Thread(new ThreadTest(new Test()));
Thread thread2 = new Thread(new ThreadTest(new Test()));
service.submit(thread1);
service.submit(thread2);
service.shutdown();
}
}
// 其他代码与上面相同省略
输出结果:
Start
Start
End
End
可以看到,对不同对象这样加锁就不产生作用了