synchronized 简介
synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象; 2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象; 3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象; 4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
synchronized使用
synchronized 修饰代码块
synchronized后跟括号,括号里是变量,这样,一次只有一个线程进入该代码块。
例如:
public static void main(String[] args) { TestSyn TestSyn = new TestSyn(); Thread test1 = new Thread( TestSyn, "Thread-1"); Thread test2 = new Thread(TestSyn, "Thread-2"); test1.start(); test2.start(); } @Override public void run() { synchronized (this) { int i=0; while (i<5) { System.out.println(Thread.currentThread().getName()+":"+i); i++; } } }
运行结果如下:
Thread-1:0 Thread-1:1 Thread-1:2 Thread-1:3 Thread-1:4 Thread-2:0 Thread-2:1 Thread-2:2 Thread-2:3 Thread-2:4
当两个并发线程(thread1和thread2)访问同一个对象(syncThread)中的synchronized代码时 在同一时刻只能有一个线程得到执行, 另一个线程受阻塞,必须等待当前线程执行完这个代码块以后才能执行该代码块。
当两个线程都是新建一个对象去执行的,对象的锁也是两个,方法就会同时执行
public static void main(String[] args) { TestSyn TestSyn = new TestSyn(); TestSyn TestSyn2 = new TestSyn(); Thread test1 = new Thread( TestSyn, "Thread-1"); Thread test2 = new Thread(TestSyn2, "Thread-2"); test1.start(); test2.start(); } @Override public void run() { synchronized (this) { int i=0; while (i<5) { System.out.println(Thread.currentThread().getName()+":"+i); i++; } } }
运行结果如下:
Thread-1:0 Thread-2:0 Thread-2:1 Thread-2:2 Thread-2:3 Thread-2:4 Thread-1:1 Thread-1:2 Thread-1:3 Thread-1:4
synchronized 修饰方法
方法声明时使用,放在范围操作符(public等)后,其返回类型声明(void等)之前。即一次只能有一个线程进入该方法,其他线程要想在此时调用该方法,只能排队等候,当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入.
例如:
public static void main(String[] args) { TestSyn TestSyn = new TestSyn(); Thread test1 = new Thread( TestSyn, "Thread-1"); Thread test2 = new Thread(TestSyn, "Thread-2"); test1.start(); test2.start(); } @Override public synchronized void run() { for (int i = 0; i < 5; i++) { System.out.println( Thread.currentThread().getName() + ":"+i); } }
synchronized 修饰静态方法
synchronized修饰的静态方法锁定的是这个类的所有对象。
例如:
public static void main(String[] args) { TestSyn TestSyn = new TestSyn(); Thread test1 = new Thread( TestSyn, "Thread-1"); Thread test2 = new Thread(TestSyn, "Thread-2"); test1.start(); test2.start(); } @Override public void run() { method(); } public synchronized static void method() { for (int i = 0; i < 5; i++) { System.out.println( Thread.currentThread().getName() + ":"+i); } }
synchronized 修饰类
synchronized后面括号里是一对象,给class加锁和上面的给静态方法加锁的方式是一样的,所有对象都共用同一把锁。
例如:
public static void method() { synchronized(TestSyn.class) { for (int i = 0; i < 5; i ++) { System.out.println(Thread.currentThread().getName() + ":" + i); } } } public synchronized void run() { method(); } }
总结
- 无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;
- 如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁。
- 每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。