java的aop是线程安全_Java 并发编程:synchronized关键字和Lock关键字

如何使用synchronized实现同步访问,在java5.0之后,在java.util.concurrent.locks包下提供了另外一种方式来实现同步访问,那就是Lock。此处简单介绍了如何使用synchronized防止并发访问,和使用synchronized存在的缺陷,以及使用Lock来控制程序的并发访问。

并发编程三个概念

原子性: 一个操作或多个操作要么全部执行且执行过程不被中断,要么不执行

可见性: 多个线程修改同一个共享变量时,一个线程修改后,其他线程能马上获得修改后的值

有序性 : 程序执行的顺序按照代码的先后顺序执行

一、synchronized关键字是为了线程安全服务的,线程安全就是当多个线程访问一个类(变量或方法)的时候,这个对象都可以表现出正常的行为。那线程的安全性又表现出三个特性:原子性、可见性及有序性。synchronized保证了同步,原子性。volatile关键字保证了可见性。wait,notify 负责多个线程之间的通信。

synchronized 可以在任意对象及方法上加锁,若一个线程想要执行synchronized修饰的代码块,首先要

step1 尝试获得锁

step2 如果拿到锁,执行synchronized代码体内容

step3 如果拿不到锁,这个线程就会不断的尝试获得这把锁,直到拿到为止,而且是多个线程同时去竞争这把锁。

注*(线程多了也就是会出现锁竞争的问题,多个线程执行的顺序是按照CPU分配的先后顺序而定的,而并非代码执行的先后顺序)

synchronized 可以修饰方法,修饰代码块,这些都是对象锁。若和static一起使用,则升级为类锁。建议修饰代码块,减小锁的颗粒度,提高系统的性能。

synchronized 锁是可以重入的,当一个线程得到了一个对象的锁后,再次请求此对象时是可以再次得到该对象的锁。锁重入的机制,也支持在父子类继承的场景。

synchronized 同步异步,一个线程得到了一个对象的锁后,其他线程是可以执行非加锁的方法(异步)。但是不能执行其他加锁的方法(同步)。

synchronized 锁异常,当一个线程执行的代码出现异常时,其所持有的锁会自动释放。

private void thisLock () { // 使用对象锁

synchronized (this) {

System.out.println("this 对象锁!");

}

}

private void classLock () { // 使用类锁

synchronized (ITDragonSynchronized.class) {

System.out.println("class 类锁!");

}

}

目前可以使用的场景,在使用单例模式的时候可以使用synchronized关键字,进行二次验证,防止在并发的情况下创建出多个对象。

// 公共静态成员方法,返回唯一实例

public static LoadBalancer GetLoadBalancer(){

// 第一重判断

if (instance == null){

// 锁定代码块

synchronized(syncLocker){

// 第二重判断

if (instance == null){

instance = new LoadBalancer();

}

}

}

return instance;

}

二、volatile关键字虽然不具备synchronized关键字的原子性(同步)但其主要作用就是使变量在多个线程中可见。也就是可见性。用法很简单,直接用来修饰变量。因为其不具备原子性。

volatile 关键字工作原理每个线程都有自己的工作内存,如果线程需要用到一个变量的时,会从主内存拷贝一份到自己的工作内存中。从而提高了效率。每次执行完线程后再将变量从工作内存同步回主内存中。

这样就存在一个问题,变量在不同线程中可能存在不同的值。如果用volatile 关键字修饰变量,则会让线程的执行引擎直接从主内存中获取值。

678dd73937fab6a9c5595971a65abd82.png

三、synchronized的缺陷

如果一个代码块被synchronized修饰了,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况:

1)获取锁的线程执行完了该代码块,然后线程释放对锁的占有;

2)线程执行发生异常,此时JVM会让线程自动释放锁;

因此就需要有一种机制可以不让等待的线程一直无期限地等待下去(比如只等待一定的时间或者能够响应中断),通过Lock就可以办到,注意:

1)Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。Lock是一个类,通过这个类可以实现同步访问;

2)Lock和synchronized有一点非常大的不同,采用synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象

使用Lock必须在try{}catch{}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被被释放,防止死锁的发生

首先要说明的就是Lock,通过查看Lock的源码可知,Lock是一个接口:

public interface Lock {

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值