用法
- 用在 非静态方法 上(执行该方法的时候,对这个对象进行加锁)
- 用在 静态方法 上(执行该方法的时候,对整个类进行加锁)
- 在 代码块 中对某个对象加锁(在执行该代码块的时候,对该对象进行加锁)
- 在 代码块 中对某个类进行加锁(在执行该代码块的时候,对该类进行加锁)
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");}}输出结果:StartEndStartEnd
可以看到,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();}}输出结果:StartStartEndEnd
对于不同的对象,执行的过程不是同步的,可知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");}}输出结果:StartEndStartEnd
静态方法是属于类的属性,存放在方法区中,与实例对象无关,所以 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");}}}输出结果:StartEndStartEnd
对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");}}输出结果:StartEndStartEnd
在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();}}// 其他代码与上面相同省略输出结果:StartStartEndEnd
可以看到,对不同对象这样加锁就不产生作用了
