Java中的锁

概述

在多线程编程中,当存在资源竞争时,多线程环境就可能会导致程序的结果是一个非预期结果,也称之为程序是非线程安全的。

public Test{
	private int i;
	public void add(){
		i++;
	}
	public int get(){
		return i;	
	}
}

上面这段代码在多线程环境下,线程之间存在成员变量i的竞争关系。当一个线程调用add方法时,另外一个线程也调用了add方法,可是此时两个线程对i的修改是彼此不可见的。因为线程之间没有实现通信(一个线程对i的修改对于其他所有线程都是可见的),所有导致了最终结果发生异常。

synchronized锁

Java中的锁是用来控制多个线程访问共享资源的方式,分为阻塞型锁和非阻塞性锁。阻塞型锁的代表就是synchronized,synchronized可以同步代码块、同步方法、同步类。synchronize的机制是阻塞性机制,也就是同一时刻只会有一个线程获得锁执行synchronize同步部分。synchronize是非公平锁,即每次获得锁的操作是不考虑请求顺序的先后的。
其他线程想要执行同步部分,必须先阻塞,等待获得锁的线程释放锁之后,再去竞争获得锁。

public Test{
   private int i;
   public void add(){
   	synchronize(this){
   	i++;
   	}
   }
   
   public int get(){
   	return i;	
   }
}

上述代码对i++操作进行同步,也就意味着同一时刻只会有一个线程对i进行修改。其他线程想要修改i必须竞争获得锁才能执行i++。

优点

synchronize是jvm自身特性,较新版本的jvm对synchronize做了较多的优化。并且synchronize会自动释放锁,从而不会因为锁未释放而导致的死锁现象。

缺点

synchronize是阻塞性锁,线程的阻塞会引起cpu对线程的调度,效率会降低。synchronize不可中断,一旦获得锁之后必须要将同步部分执行完之后才会释放锁。synchronize在高并发环境下并不适用。

Lock接口

ReentrantLock 是 java.util.concurrent(J.U.C)包中的锁,ReentrantLock 是jdk实现的。

public class LockExample {

    private Lock lock = new ReentrantLock();

    public void func() {
        lock.lock();
        try {
            for (int i = 0; i < 10; i++) {
                System.out.print(i + " ");
            }
        } finally {
            lock.unlock(); // 确保释放锁,从而避免发生死锁。
        }
    }
}

使用ReentrantLock一定要有锁释放操作,否则有可能引起死锁。

内存模型的三大特性

原子性

Java 内存模型保证了 read、load、use、assign、store、write、lock 和 unlock 操作具有原子性。例如对一个int型变量赋值的过程就是原子性的。本人对于原子性的理解就是这个操作不能再被分解成更单位化的操作就称这个操作具有原子性。
例如:
int a = 1;
这个操作不能被分解
a++;
对于a++这个操作,它是分两步的,第一先读取a的值,第二步是将a + 1的值赋给a。所以这个操作不是一个原子性的操作。

有序性

Java内存模型保证在同一线程观察,所以操作都是有序的。但是放在线程环境下就是不能保证了。

可见性

可见性指当一个线程修改了共享变量的值,其它线程能够立即得知这个修改。Java 内存模型是通过在变量修改后将新值同步回主内存,在变量读取前从主内存刷新变量值来实现可见性的。

volatile关键字只能保证对变量的读写操作的有序性和变量的可见性,它不能保证变量操作的原则性。例如 volatile int a; a++;这个操作就不是原子性的操作。

CAS

CAS是一种乐观并发策略,属于非阻塞同步。先进行操作,如果没有其它线程争用共享数据,那操作就成功了,否则采取补偿措施(不断地重试,直到成功为止)。
CAS即比较并交换,CAS操作一般都会有一个旧预期值和新值,当内存中的值等于预期值时,才会将内存值更新为新值。CAS代码一般都是一个死循环,当满足上述条件时才会退出循环。
CAS操作存在的问题:

  1. ABA问题
    当一个变量初始读取的值是A,然后被修改成B,最后又被修改回A。这对于CAS操作来说对于这个变量是没有发生修改的。可以加入版本号来解决ABA问题,不过ABA问题一般不会影响程序的执行。
  2. 循环时间长,开销大
    如果一个CAS操作一直不成功,对于CPU的开销是巨大的。
  3. 只能保证一个共享变量的原子操作
    对多个变量操作时,CAS无法保证操作的原子性
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值