Java基础: 锁及背后相关的原理

本文详细介绍了Java中线程安全问题及其解决方案,重点探讨了Synchronized关键字的使用、分类和底层实现原理。内容包括Synchronized的对象锁和类锁、自旋锁、自适应自旋锁、锁消除、锁粗化以及四种锁状态(无锁、偏向锁、轻量级锁、重量级锁)。同时,文章对比了Synchronized与ReentrantLock的区别,并讨论了Java内存模型(JMM)中的可见性问题,包括happens-before原则、Volatile的内存语义以及CAS操作。最后,简要介绍了乐观锁和悲观锁的概念和应用场景。
摘要由CSDN通过智能技术生成

前言

在Java编程中有一个每个程序猿想躲躲不开遇到了又十分头疼的问题,即多线程的线程安全问题。这块知识应该可以算是Java中比较麻烦的一块知识之一了,今天就来谈一谈Java中如何解决线程安全问题,以及各种锁的区别。

线程安全问题的主要诱因

1.存在共享数据(临界资源)

2.存在多条线程共同操作这些数据

解决问题的根本方法:同一时刻有且只有一个线程在操作共享数据,其它线程必须等到该线程处理完数据后再对共享数据进行操作。

Synchronized

  • 互斥锁的特性

互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程的协调机制,这样在同一时间只有一个线程对需要同步的代码块(复合操作)进行访问。互斥性也称为操作的原子性。
可见性:必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得锁的另一个线程是可见的(即在获得锁时应获得最新共享变量的值),否则另一个线程可能是在本地缓存的某个副本上继续操作,从而引起不一致。

对于Java来说,Synchronized关键字可以满足上述两种特性。
注:Synchronized锁的不是代码,而是对象

Synchronized关于获取锁的分类

对象锁

获取对象锁的两种用法:
1.同步代码块(synchronized(this),synchronized(类实例对象)),锁是括号中的对象。
2.同步非静态方法(synchronized method),锁是当前对象的实例。

类锁

获取类锁的两种用法:
1.同步代码块(synchronized(对象.getClass()),synchronized(类名.class)),锁是括号内对象的类对象(class对象)。
2.同步静态方法(synchronized static method),锁是当前对象的class对象。

对象锁和类锁测试

代码
ThreadDemo.java:

public class ThreadDemo implements Runnable{
   
    public void asynMethod() {
   
        System.out.println(Thread.currentThread().getName()+" 开始运行(异步方法)");
        try {
   
            Thread.sleep(1000);
        } catch (InterruptedException e) {
   
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+" 结束运行(异步方法)");
    }
    public synchronized void syncMethod() {
   
        System.out.println(Thread.currentThread().getName()+" 开始运行(同步方法)");
        try {
   
            Thread.sleep(1000);
        } catch (InterruptedException e) {
   
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+" 结束运行(同步方法)");
    }
    public void syncBlock() {
   
        synchronized(this) {
   
            System.out.println(Thread.currentThread().getName()+" 开始运行(同步代码块)");
            try {
   
                Thread.sleep(1000);
            } catch (InterruptedException e) {
   
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" 结束运行(同步代码块)");
        }
    }
    public void syncClass() {
   
        synchronized (this.getClass()) {
   
            System.out.println(Thread.currentThread().getName()+" 开始运行(以class文件为锁对象的同步代码块)");
            try {
   
                Thread.sleep(1000);
            } catch (InterruptedException e) {
   
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" 结束运行(以class文件为锁对象的同步代码块)");
        }
    }
    public static synchronized void syncStaticMethod() {
   
        System.out.println(Thread.currentThread().getName()+" 开始运行(静态同步方法(以class文件为锁))");
        try {
   
            Thread.sleep(1000);
        } catch (InterruptedException e) {
   
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+" 结束运行(静态同步方法(以class文件为锁))");
    }
    @Override
    public void run() {
   
    	// TODO Auto-generated method stub
        if(Thread.currentThread().getName().startsWith("ASYN")) {
   
            asynMethod();
        }else if(Thread.currentThread().getName().startsWith("SYNC_METHOD")) {
   
            syncMethod();
        }else if(Thread.currentThread().getName().startsWith("SYNC_BLOCK")) {
   
            syncBlock();
        }else if(Thread.currentThread().getName().startsWith("SYNC_CLASS")) {
   
            syncClass();
        }else if(Thread.currentThread().getName().startsWith("SYNC_STATIC")) {
   
            syncMethod();
        }
    }
}

ThreadTest.java:

public class ThreadTest {
   
    public static void main(String[] args) {
   
        ThreadDemo threadDemo = new ThreadDemo();
        Thread thread1 = new Thread(threadDemo,"ASYN_Thread1");
        Thread thread2 = new Thread(threadDemo,"ASYN_Thread2");
        Thread thread3 = new Thread(threadDemo,"SYNC_METHOD_Thread1");
        Thread thread4 = new Thread(threadDemo,"SYNC_METHOD_Thread2");
        Thread thread5 = new Thread(threadDemo
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值