Synchronized 关键
synchronized 是 Java 中的关键字,是一种同步锁。它修饰的对象有以下几种:
1.修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}
括起来的代码,作用的对象是调用这个代码块的对象;
2.修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
虽然可以使用 synchronized 来定义方法,但synchronized 并不属于方法定义
的一部分,因此,synchronized 关键字不能被继承。如果在父类中的某个方法
使用了 synchronized 关键字,而在子类中覆盖了这个方法,在子类中的这个方
法默认情况下并不是同步的,而必须显式地在子类的这个方法中加上synchronized 关键字才可以。当然,还可以在子类方法中调用父类中相应的方
法,这样虽然子类中的方法不是同步的,但子类调用了父类的同步方法,因此,子类的方法也就相当于同步了。
3.修饰一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4.修饰一个类,其作用的范围是 synchronized 后面括号括起来的部分,作用主
的对象是这个类的所有对象。
对象锁:包括方法锁(默认锁对象为this,当前实例对象)和同步代码块锁(自己指定锁对象)
著作权归https://pdai.tech所有。 链接:https://pdai.tech/md/java/thread/java-thread-x-key-synchronized.html public class SynchronizedObjectLock implements Runnable { static SynchronizedObjectLock instence = new SynchronizedObjectLock(); @Override public void run() { // 同步代码块形式——锁为this,两个线程使用的锁是一样的,线程1必须要等到线程0释放了该锁后,才能执行 synchronized (this) { System.out.println("我是线程"+ Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"结束"); } } public static void main(String[] args) { Thread t1 = new Thread(instence); Thread t2 = new Thread(instence); t1.start(); t2.start(); } }
输出结果:
我是线程Thread-0 Thread-0结束 我是线程Thread-1 Thread-1结束
public class SynchronizedObjectLock implements Runnable { static SynchronizedObjectLock instence = new SynchronizedObjectLock(); // 创建2把锁 Object block1 = new Object(); Object block2 = new Object(); @Override public void run() { // 这个代码块使用的是第一把锁,当他释放后,后面的代码块由于使用的是第二把锁,因此可以马上执行 synchronized (block1) { System.out.println("block1锁,我是线程"+ Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("block1锁,"+Thread.currentThread().getName() +"结束"); } synchronized (block2) { System.out.println("block2锁,我是线程"+ Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("block2锁,"+Thread.currentThread().getName() +"结束"); } } public static void main(String[] args) { Thread t1 = new Thread(instence); Thread t2 = new Thread(instence); t1.start(); t2.start(); } }
结果:
block1锁,我是线程Thread-0 block1锁,Thread-0结束 block2锁,我是线程Thread-0 // 可以看到当第一个线程在执行完第一段同步代码块之后,第二个同步代码块可以马上得到执行,因为他们使用的锁不是同一把 block1锁,我是线程Thread-1 block2锁,Thread-0结束 block1锁,Thread-1结束 block2锁,我是线程Thread-1 block2锁,Thread-1结束
方法锁形式:synchronized修饰普通方法,锁对象默认为this
著作权归https://pdai.tech所有。 链接:https://pdai.tech/md/java/thread/java-thread-x-key-synchronized.html public class SynchronizedObjectLock implements Runnable { static SynchronizedObjectLock instence = new SynchronizedObjectLock(); @Override public void run() { method(); } public synchronized void method() { System.out.println("我是线程"+ Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"结束"); } public static void main(String[] args) { Thread t1 = new Thread(instence); Thread t2 = new Thread(instence); t1.start(); t2.start(); } }
输出结果:
我是线程Thread-0 Thread-0结束 我是线程Thread-1 Thread-1结束
类锁:指synchronize修饰静态的方法或指定锁对象为Class对象
synchronize修饰静态方法
public class SynchronizedObjectLock implements Runnable { static SynchronizedObjectLock instence1 = new SynchronizedObjectLock(); static SynchronizedObjectLock instence2 = new SynchronizedObjectLock(); @Override public void run() { method(); } // synchronized用在普通方法上,默认的锁就是this,当前实例 public synchronized void method() { System.out.println("我是线程"+ Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"结束"); } public static void main(String[] args) { // t1和t2对应的this是两个不同的实例,所以代码不会串行 Thread t1 = new Thread(instence1); Thread t2 = new Thread(instence2); t1.start(); t2.start(); } }
输出结果
我是线程Thread-0 我是线程Thread-1 Thread-1结束 Thread-0结束
实例2:
public class SynchronizedObjectLock implements Runnable { static SynchronizedObjectLock instence1 = new SynchronizedObjectLock(); static SynchronizedObjectLock instence2 = new SynchronizedObjectLock(); @Override public void run() { method(); } // synchronized用在静态方法上,默认的锁就是当前所在的Class类,所以无论是哪个线程访问它,需要的锁都只有一把 public static synchronized void method() { System.out.println("我是线程"+ Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"结束"); } public static void main(String[] args) { Thread t1 = new Thread(instence1); Thread t2 = new Thread(instence2); t1.start(); t2.start(); } }
输出结果:
我是线程Thread-0 Thread-0结束 我是线程Thread-1 Thread-1结束
synchronized指定锁对象为Class对象
public class SynchronizedObjectLock implements Runnable { static SynchronizedObjectLock instence1 = new SynchronizedObjectLock(); static SynchronizedObjectLock instence2 = new SynchronizedObjectLock(); @Override public void run() { // 所有线程需要的锁都是同一把 synchronized(SynchronizedObjectLock.class){ System.out.println("我是线程"+ Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"结束"); } } public static void main(String[] args) { Thread t1 = new Thread(instence1); Thread t2 = new Thread(instence2); t1.start(); t2.start(); } }
输出结果:
我是线程Thread-0 Thread-0结束 我是线程Thread-1 Thread-1结束