java锁的实现原理_java锁原理分析

本文详细介绍了Java中synchronized关键字和Lock接口的实现原理,包括对象锁、类锁、同步代码块、同步方法等,并探讨了锁的优化,如偏向锁、轻量级锁、自旋锁。文章还讨论了线程中断与synchronized的关系,并通过实例展示了中断线程在同步方法中的行为。最后,提到了Lock接口及其在响应中断方面的优势。
摘要由CSDN通过智能技术生成

前言

在编程中,很多人都会尝试使用多线程的方式去编程,但是却很难保证自己写出来的多线程程序的正确性,在多线程中如果涉及到对共享资源的并发读写,这时就会产生资源的争夺。而在资源争夺中,第一想到的就是使用锁 ,对共享资源进行数据保护。java中提供了2种基本也是最常用的锁,synchronized、Lock!但是这2种锁有什么特点?分别使用的场景?在使用过程中应该注意哪些?各自有哪些不足呢?

本文将带着上面的问题并结合源码进行仔细分析,让你对锁有一个深入的了解。

synchronized 详解

一、概念

synchronized 是java中的关键字,利用锁的机制来实现同步,来达到对共享资源保护。

锁的机制有2种特质:

1、互斥性:在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机制。互斥性我们往往称作原子性

2、可见性:确保在锁被释放之前,对共享变量所做的修改,对其余的线程是可见的(也就是说在获得锁的时候应获得最新的共享变量值),否则对于另外一个线程在操作共享变量是自己在本地缓存的副本上,这样就会引发数据的不一致。

二、对象锁和类锁

在使用Synchronized之前,先了解什么是对象锁和类锁

1、对象锁

在java中,每个对象都会有一个monitor对象,这个对象其实就是java对象锁,通常也被称作为"内置锁"或"对象锁",类的对象有多个,所有对象锁也有多个,相互之间互不干涉。

2、类锁

在java中,针对每一个类都有一个帧,可以称作为"类锁",类锁实际也是通过对象锁实现的,即类的Class对象锁,每一个类有且仅有一个Class对象(JVM加载类的时候产生),所有每一个类只有一个类锁。

三、修饰方法

1、修饰实例方法:作用于当前实例加锁,在进入同步代码方法时先获取当前实例锁

2、修饰静态方法:作用于当前类对象锁,在进入同步代码方法时先获取当前对象锁(类.class)

修饰实例方法:

顾名思义就是修饰类中的实例方法,并且默认是当前对象作为锁的对象,而一个对象只有一把锁,所以同一时刻只能有一个线程执行被同步的方法,等到线程执行完方法后,其他线程才能继续执行被同步的方法。正确实例代码如下:

public class SynchronizedTest implements Runnable {

public static int count = 0;

@Override

public void run() {

for (int i = 1; i <= 1000000; i++) {

add();

}

}

public synchronized void add() {

++count;

}

public static void main(String[] args) throws Exception {

SynchronizedTest test = new SynchronizedTest();

Thread t1 = new Thread(test);

Thread t2 = new Thread(test);

t1.start();

t2.start();

t1.join();

t2.join();

System.out.println(count); //2000000

}

}

错误代码:对同一共享资源使用不同实例锁

public class SynchronizedTest implements Runnable {

private Object object;

public SynchronizedTest(Object object) {

this.object = object;

}

public static int count = 0;

@Override

public void run() {

synchronized (object) {

for (int i = 1; i <= 1000000; i++) {

add();

}

}

}

public static void add() {

++count;

}

public static void main(String[] args) throws Exception {

Object object1 = new Object();

Object object2 = new Object();

SynchronizedTest firstLock = new SynchronizedTest(object1);

SynchronizedTest secondLock = new SynchronizedTest(object2);

Thread t1 = new Thread(firstLock);

Thread t2 = new Thread(secondLock);

t1.start();

t2.start();

t1.join();

t2.join();

System.out.println(count);//小于 20000000

}

}

运行程序后,会发现结果永远小于2000000,说明synchronized没有起到同步的作用了,说明修饰实例方法只能作用实例对象,不能作用到类对象

修饰静态方法:

public class SynchronizedTest implements Runnable {

public static int count = 0;

@Override

public void run() {

for (int i = 1; i <= 100000; i++) {

add();

}

}

public static synchronized void add() {

++count;

}

public static void main(String[] args) throws Exception {

SynchronizedTest firstLock = new SynchronizedTest();

SynchronizedTest secondLock = new SynchronizedTest();

Thread t1 = new Thread(firstLock);

Thread t2 = new Thread(secondLock);

t1.start();

t2.start();

t1.join();

t2.join();

System.out.println(count);=2000000

}

}

作用与静态方法的时候,不管实例化多少个实例对象,结果用于等2000000,说明锁对象是当前类.class,有且仅有一把锁,最终结果和实际结果一致!

修饰代码块:正确案例

ppublic class SynchronizedTest implements Runnable {

private Object object;

public SynchronizedTest(Object object) {

this.object = object;

}

public static int count = 0;

@Override

public void run() {

synchronized (object) {

for (int i = 1; i <= 1000000; i++) {

add();

}

}

}

public static void add() {

++count;

}

public static void main(String[] args) throws Exception {

Object object = new Object();

SynchronizedTest firstLock = n

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值