java 对象锁学习

机制

  锁机制是用来解决多线程共享资源时产生的冲突问题的。java 为每一个对象关联一个对象锁,通常把锁分为对象锁和类锁,他们的本质都是对象锁,只不过对象锁关联的是类的 Object 对象 (java.lang.Object),而类锁关联的是类的 Class 对象 java.lang.Class。
  jvm 对每个锁都有一个计数

  • 若该计数为 0,则锁没有被占用,可以被访问它的线程来持有

  • 一个对象的对象锁已被某个线程持有,新的线程来访问时将被挂起,知道持有它的线程释放该锁并且计数为 0
  • 一个线程已经持有了某个对象的锁,该线程再次访问该对象锁时可以重入,且计数 +1
  • 一个线程释放对象锁时,该锁的计数 -1,当某个锁的计数为 0 时锁被释放,可以被线程竞争

分类

  • 不管怎么分类,java 中通过 synchronized 来实现的锁其本质都是对象锁

  • java 内部同步机制实现通常有两种方式,synchronized 修饰方法和语句块
  • synchronized 关键字作用于对象,这个对象可以是类的实例对象,也可以是 Class 对象

    • 类锁

  1 public class SyncObject {
  2     // 类锁1:通过static方法加同步锁
  3     public static synchronized void syncMethod1() {
  4         try {
  5             System.out.println("testMethod1 start!");
  6             Thread.sleep(3000);
  7         } catch (InterruptedException e) {
  8             e.printStackTrace();
  9         }
 10         System.out.println("testMethod1 end!");
 11     }
 12
 13     public void syncMethod2() {
 14         // 类锁2:通过同步语句块传递Class类型参数
 15         synchronized (SyncObject.class) {
 16             try {
 17                 System.out.println("testMethod2 start!");
 18                 Thread.sleep(3000);
 19             } catch (InterruptedException e) {
 20                 e.printStackTrace();
 21             } finally {
 22                 System.out.println("testMethod2 end!");
 23             }
 24         }
 25     }
 26 }

类锁作用于类的 Class 对象,对一个类来说,无论该类有多少个实例,它的静态变量和静态方法都只有一份,保存在 Class 对象中。通过对 Class 对象加锁来实现的同步语句或同步方法,无论该对象的哪个实例来访问,都需要竞争这个类锁

  • 对象锁

  1 public class SyncObject {
  2     // 对象锁1(方法锁):通过方法加同步锁
  3     public synchronized void syncMethod1() {
  4         try {
  5             System.out.println("testMethod1 start!");
  6             Thread.sleep(3000);
  7         } catch (InterruptedException e) {
  8             e.printStackTrace();
  9         }
 10         System.out.println("testMethod1 end!");
 11     }
 12
 13     public void syncMethod2() {
 14         // 对象锁2:通过同步语句块传递Object类型参数
 15         synchronized (this) {
 16         // 此处的参数可以是本实例this,也可以是其它实例比如new SyncObject(),传入哪个实例就对哪个实例加锁
 17             try {
 18                 System.out.println("testMethod2 start!");
 19                 Thread.sleep(3000);
 20             } catch (InterruptedException e) {
 21                 e.printStackTrace();
 22             } finally {
 23                 System.out.println("testMethod2 end!");
 24             }
 25         }
 26     }
 27 }

对象锁会对类的实例对象加锁,每一个 new 操作都会获得一个新的实例对象,对于 synchronized 修饰的非 static 方法或传递参数为实例对象的语句块,各个实例对象会拥有自己的锁。

TIPS

    • synchronized 的作用范围是对象

    • synchronized 修饰的代码块需要传入一个对象参数(这个对象可以使 Class 对象),这个对象参数就是它的作用范围
    • synchronized 修饰的非静态方法的作用范围是 this,即当前对象实例。修饰静态方法时作用范围是这个类,即 Class 对象
  1. synchronized 的粒度针不可再分

    因为锁是针对整个对象的,所以当某个对象的锁被持有后,其它线程不能持有该锁

    • 当一个线程调用某个对象 a 的 synchronized 方法(a.syncMethod1)在该方法结束之前,该对象的其它 synchronized 方法 (a.syncMethod2..) 都将不能被调用。同步代码块 synchronized(a)与 a.syncMethod1 有同样的作用周期

    • 当一个线程调用某个类 A 的 static synchronized 方法(A.staticSyncMethod1)在该方法结束前,该类的其它 static synchronized 方法(A.staticSyncMethod2..)都将不能被调用
    • 当一个线程调用某个对象 a 的 synchronized 方法(a.syncMethod1)在该方法结束之前,该类的其它 static synchronized 方法 (A.syncMethod2..) 还可以被调用,反之也成立
    • synchronized 的只对它修饰的模块加锁

    • 未被 synchronized 修饰的模块是可以被异步访问的, 因为线程访问它的时候并不需要获取对象锁
时间: 2024-10-20 03:16:33

java 对象锁学习的相关文章

java 对象锁和类锁的区别(转)

java 对象锁和类锁的区别   转自 <http://zhh9106.iteye.com/blog/2151791> 在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁.线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁.获得内置锁的唯一途

java对象锁和类锁

参考 http://www.cnblogs.com/yyyyy5101/archive/2011/07/20/2112157.html http://www.cnblogs.com/kkcheng/archive/2011/02/25/1964521.html http://my.oschina.net/billowworld/blog/120766 1.java对象锁 所有对象都自动含有单一的锁.JVM负责跟踪对象被加锁的次数.如果一个对象被解锁,其计数变为0.在任务(线程)第一次给对象加锁的

Java对象锁和类锁全面解析(多线程synchronized关键字)

最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念.最近也是遇到一些问题,不搞清楚锁的概念,很容易碰壁,甚至有些时候自己连用没用对都不知道. 今天把一些疑惑都解开了,写篇文章分享给大家,文章还算比较全面.当然可能有小宝鸽理解得不够深入透彻的地方,如果说得不正确还望指出. 看之前有必要跟某些猿友说一下,如果看一遍没有看明白呢,也没关系,当是了解一下,等真正使用到了,再回头看. 本文主要是将synchronized关键字用法作

java对象锁&amp;类锁

首先,来看一段代码. 1 public class PersonSet { 2 3 private final Set<Person> mySet = new HashSet<Person>(); 4 5 public synchronized void add(Person p){ 6 mySet.add(p); 7 } 8 9 public synchronized boolean contains(Person p){ 10 return mySet.contains(p);

Java 对象锁-synchronized()与线程的状态与生命周期

synchronized(someObject){ //对象锁 } 对象锁的使用说明: 1.对象锁的返还. 当synchronize()语句执行完成. 当synchronize()语句执行出现异常. 当线程调用了wait()方法. 2.使用对象锁保护的数据都必须是私有的. 3.对象锁具有可重入性. 一个线程在已经获得对象锁的情况下,可以再次请求获得对象锁. 4.线程的生命周期

java对象锁

在进行多线程开发时,经常会用到同步锁:synchronized.该关键字可以使用在普通方法上,也可以使用在static方法上.这里叙述下这两种方式的区别,避免以后忘记. 我们都知道,每一个对象都有一个监视器.对于每一个类,有一个Class对象,也可以有该类的实例对象.如果synchronized放在普通方法上,线程在同步访问时,就会查看该类实例对象上的监视器:如果synchronized放在static方法上,则会查看Class对象上的监视器.因为是两个不同的对象,所以这两种方式不会互相干扰,线

Java多线程 同步 对象锁

多线程.同步: https://www.cnblogs.com/GarfieldEr007/p/5746362.html Java对象锁和类锁全面解析(多线程synchronized关键字): http://blog.csdn.net/u013142781/article/details/51697672 Java Object对象中的wait,notify,notifyAll通俗理解 http://blog.csdn.net/vk5176891/article/details/53945677

Java学习(十一):Java锁Synchronized,对象锁和类锁举例

Java的锁分为对象锁和类锁. 1. 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内针对该对象的操作只能有一个线程得到执行.另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块. 2. 然而,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块. 3. 尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对该object中所有其它sync

java基础知识回顾之java Thread类学习(六)--java多线程同步函数用的锁

1.验证同步函数使用的锁----普通方法使用的锁 思路:创建两个线程,同时操作同一个资源,还是用卖票的例子来验证.创建好两个线程t1,t2,t1线程走同步代码块操作tickets,t2,线程走同步函数封装的代码操作tickets,同步代码块中的锁我们可以指定.假设我们事先不知道同步函数用的是什么锁:如果在同步代码块中指定的某个锁(测试)和同步函数用的锁相同,就不会出现线程安全问题,如果锁不相同,就会发生线程安全问题. 看下面的代码:t1线程用的同步锁是obj,t2线程在操作同步函数的资源,假设不