synchronized 是用来处理多个线程访问同一个代码块或者是方法,或者是一个类。
方法锁:
每个类的对象对应一个锁,当对象中的某个方法被synchronized修饰后,调用该方法的时候必须获得该对象的“锁”
。该方法一旦执行就会占有该锁,别的线程使用该对象调用这个方法的时候就会被阻塞直到这个方法执行完后释放锁,被阻塞的线程才能获得锁,从而进入执行状态。
这种机制确保了在同一时刻,对于每一个对象的实例,其所有声明为synchronized方法中最多只有一个处于可执行状态。从而避免了类成员变量的访问冲突。
1,当使用同一个对象调用加了synchronized修饰的方法,如下所示。
public class Demo4 { public static void main(String[] args) { Demo4 d = new Demo4(); new Thread(){ public void run() { d.method1(); }; }.start(); new Thread(){ public void run() { d.method2(); }; }.start(); } public synchronized void method1(){ System.out.println("method1------开始"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("method1------结束"); } public synchronized void method2(){ System.out.println("method2------开始"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("method2------结束"); } }
结果如下:
method1------开始
method1------结束
method2------开始
method2------结束
由此可得,当使用第一个线程调用method1的时候,method1就会获得当前对象的锁,然后进入方法,在这个时候线程二执行method2方法的时候是进不去的,因为当前对象d的锁已经被method1方法获取到。所以线程二执行method2方法的时候获取不到锁,只能阻塞,然后等待method1方法释放锁后method2才得以执行。
当使用不同的对象调用加了synchronized修饰的方法,如下所示。
ublic class Demo4 { public static void main(String[] args) { Demo4 d1 = new Demo4(); Demo4 d2 = new Demo4(); new Thread(){ public void run() { d1.method1(); }; }.start(); new Thread(){ public void run() { d2.method2(); }; }.start(); } public synchronized void method1(){ System.out.println("method1------开始"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("method1------结束"); } public synchronized void method2(){ System.out.println("method2------开始"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("method2------结束"); } }
结果入下:
method1------开始
method2------开始
method2------结束
method1------结束
有结果可以得出:使用不同的对象调用这两个方法,可以看到这两个方法是同时执行的。因为调用方法的对象不同,所以两个方法获取到的锁也不同,结果就是这两个方法分别获取了这两个对象的锁。然后两个方法会同时执行。
对象锁:
当一个对象中有synchronized方法或者sychronized代码块的时候。调用此对象方法的时就必须获取对象锁,如果此对象的锁已被别的线程获取,那么就必须等待别的线程释放锁后才可以 执行该方法(方法锁也是对象锁)。
方法锁和对象锁都差不多,方法锁针对的是一个方法。对象锁则是一个代码块,针对的是一部分代码。
对象锁和方法锁的两种形式。
1,方法锁:
public synchronized void method1(){ System.out.println("method1------开始"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("method1------结束"); }
2,代码块:
public void method2(){ synchronized(this){ System.out.println("method2------开始"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("method2------结束"); } }
类锁:
synchronized修饰的代码块或者synchronized修饰的静态方法。
由于一个类不论被实例化多少次,这个类中的静态方法和变量只会被加载和初始化一份,一旦某个静态方法被修饰为synchronized,此类的所有实例化对象共用一把锁,称之为类锁。
类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的
如下两种形式:
静态synchronized:
public static synchronized void method1(){ System.out.println("method1------开始"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("method1------结束"); }
代码块类锁:
public void method2(){ synchronized(Demo4.this){ System.out.println("method2------开始"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("method2------结束"); } }
如有错误,还请指出,谢谢!