方法锁、对象锁、类锁的意义和区别

简介: 方法锁、对象锁、类锁的意义和区别

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------结束");
  }
   }


如有错误,还请指出,谢谢!


相关文章
|
3月前
|
Java
锁对象
锁对象
20 5
|
4月前
|
存储 安全 Java
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)(中)
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)
91 5
|
4月前
|
安全 算法 Java
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)(下)
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)
84 6
|
4月前
|
存储 安全 Java
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)(上)
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)
87 3
|
5月前
多线程线程安全问题之synchronized和ReentrantLock在锁的释放上有何不同
多线程线程安全问题之synchronized和ReentrantLock在锁的释放上有何不同
|
6月前
|
调度
线程操作:锁、条件变量的使用
线程操作:锁、条件变量的使用
39 1
|
Java
加锁和释放锁的原理
当方法执行完后或者抛出异常后,都会释放锁
66 0
|
Java
Java 中线程同步机制synchronized,互斥锁,死锁,释放锁的详解
Java 中线程同步机制synchronized,互斥锁,死锁,释放锁的详解
104 0
|
安全 Java
synchronized 锁与 ReentrantLock 锁的区别
synchronized 锁与 ReentrantLock 锁的区别
114 0
|
安全 Java
同步代码块、同步方法解决数据安全问题、线程安全的类及Lock锁
同步代码块、同步方法解决数据安全问题、线程安全的类及Lock锁的简单示例
115 1
同步代码块、同步方法解决数据安全问题、线程安全的类及Lock锁
下一篇
DataWorks