类锁和对象锁的详解
来源:互联网 发布:网络骗局如何报警 编辑:程序博客网 时间:2024/06/05 06:49
最近在面试中遇到很多关于多线程的问题,特别是锁的应用,现在我就来说说类锁和对象锁。
对象锁(synchronized method{})和类锁(static sychronized method{})的区别
对象锁也叫实例锁,对应synchronized关键字,当多个线程访问多个实例时,它们互不干扰,每个对象都拥有自己的锁,如果是单例模式下,那么就是变成和类锁一样的功能。
对象锁防止在同一个时刻多个线程访问同一个对象的synchronized块。如果不是同一个对象就没有这样子的限制。
类锁对应的关键字是static sychronized,是一个全局锁,无论多少个对象否共享同一个锁(也可以锁定在该类的class上或者是classloader对象上),同样是保障同一个时刻多个线程同时访问同一个synchronized块,当一个线程在访问时,其他的线程等待。
代码样例
我们就拿账户存钱取钱的情景来模拟,以下是使用对象锁
Account类
public class Account { /** * 账户类 */ private static volatile int count = 100; public synchronized void add(int m){ String name = Thread.currentThread().getName(); System.out.println("对象锁添加" + m + "钱," + name + "添加后:" + (count+=m)); } public synchronized void mul(int m){ String name = Thread.currentThread().getName(); System.out.println("对象锁减少" + m + "钱," + name + "消费后:" + (count-=m)); }}
public static void main(String[] args) { CyclicBarrier barrier = new CyclicBarrier(4); Account suo = new Account(); Account suo1 = new Account(); for (int i=0;i<4;i++){ int n=i+1; int j=n*3; new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000*(new Random().nextInt(8))); System.out.println("线程"+n+"准备好了"); barrier.await(); if(n==1||n==3) suo.add(j);//1,3 else suo.mul(j);//2,4 } catch (Exception e) { e.printStackTrace(); } } },"线程"+i).start();}使用CyclicBarrier类让四个子线程都准备好了之后就开始对账户进行操作,1、3线程执行添加,2、4执行减少可以看到线程执行是同步的,多个线程没有在同一时刻去访问,如果在2、4线程的时候,执行suo1对象访问mul()方法
if(n==1||n==3) suo.add(j);//1,3 else suo1.mul(j);//2,4
可以看到结果,线程的执行不是同步的,而是异步的,所以如果想要用对象锁进行同步操作,就必须锁定同一个对象
接着继续看类锁,当多个线程执行同一个对象的加减操作时
public class Account { /** * 账户类 */ private static int count = 100; public static synchronized void add(int m){ String name = Thread.currentThread().getName(); System.out.println("类锁添加" + m + "钱," + name + "添加后:" + (count+=m)); } public static synchronized void mul(int m){ String name = Thread.currentThread().getName(); System.out.println("类锁减少" + m + "钱," + name + "消费后:" + (count-=m)); }}运行结果
从结果中也可以看出运行是同步操作的,如果同上面对象锁一样是多个线程访问多个对象操作加减方法,运行结果如下
从结果中仍然可以看出,类锁无论是访问同一个对象的synchronized块还是多个对象的,仍然是同步操作的。
总结:
1.类锁是对静态方法使用synchronized关键字后,无论是多线程访问单个对象还是多个对象的sychronized块,都是同步的。
2.对象锁是实例方法使用synchronized关键字后,如果是多个线程访问同个对象的sychronized块,才是同步的,但是访问不同对象的话就是不同步的。
3.类锁和对象锁是两种不同的锁,可以同时使用,但是注意类锁不要嵌套使用,这样子容易发生死锁。
类锁和对象锁两种使用的方式
类锁
1.代码块的方式
public void add(int m){ synchronized (Account.class){ String name = Thread.currentThread().getName(); System.out.println("类锁添加" + m + "钱," + name + "添加后:" + (count+=m)); } }
2.方法锁方式
public static synchronized void add(int m){ String name = Thread.currentThread().getName(); System.out.println("类锁添加" + m + "钱," + name + "添加后:" + (count+=m)); }
1.代码块的方式
public void add(int m){ synchronized(this){ String name = Thread.currentThread().getName(); System.out.println("对象锁添加" + m + "钱," + name + "添加后:" + (count+=m)); } }
2.方法锁的方式
public synchronized void add(int m){ String name = Thread.currentThread().getName(); System.out.println("对象锁添加" + m + "钱," + name + "添加后:" + (count+=m)); }
今天的分享就到这里
- 类锁和对象锁的详解
- synchronize类锁和对象锁详解
- synchronize类锁和对象锁详解
- 类锁和对象锁详解
- Java4Android类和对象的初始化详解
- C++类和对象的基础知识详解
- Java对象和类的详解
- ServletConfig对象和ServletContext对象的详解
- 对象封装和类--详解
- Java类和对象 详解
- 详解OC的类和对象的底层实现机制
- java的对象锁和对象传递
- Java的类锁和对象锁
- 对象锁和类锁的区别
- Java的类锁和对象锁
- 类锁和对象锁的区别
- 对象和对象锁
- Java的面向对象说明,以及类和对象的详解
- 安全hash算法,sha-1的C++实现
- JPA
- JS 实现父子窗体相互传值的三个方法
- auto与 decltype 的区别
- python学习系列(四)元组
- 类锁和对象锁的详解
- AutoCAD .Net 通过块参照获取块名
- Spring学习(4)--Spring中Bean的作用域
- 第3周 【项目4】 顺序表应用
- 灵灵兔人事考勤薪资软件系统kqwins:连接失败
- Intel's Haswell Architecture Analyzed: Building a New PC and a New Intel
- AutoCAD .Net 监测工作空间变化
- bzoj1012
- C/C++ -- 分析++和--