在代码世界游走,没几把“锁”防身可不行

打印 上一主题 下一主题

主题 864|帖子 864|积分 2592

一、开篇背景

“锁”代表安全。在程序中(这里指java)尤其多线程环境下,有了锁的帮助,会给数据安全带来保障,帮助线程更好的运作,避免竞争和互斥。
锁共有15种算法:乐观锁、悲观锁、自旋锁、重入锁、读写锁、公平锁、非公平锁、共享锁、独占锁、重量级锁、轻量级锁、偏向锁、分段锁、互斥锁、同步锁....一口气输出真的累,谁记这个啊。我们要吃现成的。ok,上面的一大堆在咱java里就是:
ReentrantLock,Synchronieed,ReentrantReadWriteLock,Atomic 全家桶,Concurrent全家桶
已上在并发场景中都是被常常用到,想必大家都已炉火纯青般.....巴特!我们还有后浪同学们可能不熟悉,那我在这里聊下锁的用法和使用场景。
ReentrantLock:

ReentrantLock是一个互斥的可重入锁。互斥的意思就是排他,独占,只能一个线程获取到锁。可重入的意思就是单个线程可以多次重复获取锁。它实现了悲观锁、重入锁、独占锁、非公平锁和互斥锁的算法。
常用方法
方法名说明异常lock()一直阻塞获取锁,直到获取成功无lockInterruptibly()尝试获取锁,直到获取锁或者线程被中断InterruptedExceptiontryLock()尝试获取空闲的锁,获取成功返回true,获取失败返回false,不会阻塞,立即返回无tryLock(long time, TimeUnit unit)尝试在time时间内获取空闲的锁,在等待时间内可以被中断InterruptedExceptionunLock()释放锁无newCondition()返回当前锁的一个condition实例,可以唤醒或等待线程无场景
递归嵌套的业务场景中,例如一棵树型的业务逻辑,方法有嵌套和调用,这时候我从外层加锁后,在递归遍历多次,每次都要是同一把锁,并且递归到其他层级时锁还不能失效。这个时候就可以使用重入锁了。江湖上还有个花名,叫递归锁。
Synchronized

Synchronized是悲观锁,默认是偏向锁,解锁失败后会升级为轻量级锁,当竞争继续加剧,进入CAS自旋10次后会升级为重量级锁。它实现了悲观锁、重入锁(用关键字修饰方法或代码段时)、独占锁,非公平锁、轻量级锁、重量级锁、偏向锁和同步锁算法。
使用方法
使用场景说明修饰方法public synchronized void someMethod()修饰代码块public void someMethod() { synchronized (lockObject) { // 临界区代码 } }修饰静态方法public static synchronized void someStaticMethod()修饰类public class MyClass { public void method1() { synchronized(MyClass.class) { // 同步代码块 } } public synchronized void method2() { // 同步方法 } }场景
多个线程访问共享变量,为了保证期原子性就可以使用 synchronized 。一个典型的业务场景是银行转账操作。假设有多个用户在同时进行转账操作,需要确保转账过程的原子性和数据的一致性,避免出现重复转账或者转账金额错误的情况。在这种情况下,可以使用 synchronized 关键字来实现同步访问。
ReentrantReadWriteLock

ReentrantReadWriteLock是Java提供的读写锁,它支持多个线程同时读取共享数据,但只允许一个线程进行写操作。 他实现了读写锁和共享锁算法。
常用方法
方法说明readLock()获取读锁writeLock()获取写锁readLock().lock()获取读锁并加锁writeLock().lock()获取写锁并加锁readLock().unlock()释放读锁writeLock().unlock()释放写锁newCondition()创建与锁相关联的Condition实例,可以唤醒或等待线程场景
读写锁应用在读多写少的情况下。读取时不涉及数据修改,写入时需要互斥操作。现在基本所有的号称效率高的准实时数据库都有实现读写锁的算法。
Atomic 全家桶

Atomic全家桶 我们已 AtomicInteger 为例。他的特点是实现了CAS算法,同时解决了ABA问题保证原子性。还实现了自旋锁的CLHLock算法,用于CAS比较失败后自旋等待。它实现了乐观锁、自旋锁和轻量级锁的算法。
常用方法
方法说明get();获取当前AtomicInteger对象的值set(int newValue);将AtomicInteger对象的值设置为指定的新值getAndSet(int newValue)将AtomicInteger对象的值设置为指定的新值,并返回设置前的旧值incrementAndGet()将AtomicInteger对象的值递增1,并返回递增后的新值decrementAndGet()将AtomicInteger对象的值递减1,并返回递减后的新值getAndIncrement()先获取AtomicInteger对象的当前值,然后将其递增1,并返回获取的旧值getAndDecrement()先获取AtomicInteger对象的当前值,然后将其递减1,并返回获取的旧值addAndGet(int delta)将指定的值加到AtomicInteger对象的当前值上,并返回相加后的结果getAndAdd(int delta)先获取AtomicInteger对象的当前值,然后将指定的值加到当前值上,并返回获取的旧值场景
用来做计数器非常合适,再有就是线程通讯,数据共享。
Concurrent全家桶

Concurrent全家桶我们已ConcurrentHashMap为代表。它实现了分段锁算法(Segmented Locking)的策略,将整个数据结构划分成多个Segments,每个段都拥有独立的锁。
常用方法
[table][tr]方法说明[/tr][tr][td]clear();[/td][td]移除所有关系[/td][/tr][tr][td]containsKey(object value);[/td][td]检查指定对象是都为表中的键[/td][/tr][tr][td]containsValue(object value);[/td][td]如果此映射将一个或多个健映射到指定值,返回true[/td][/tr][tr][td]elements()[/td][td]返回此表值的枚举[/td][/tr][tr][td]entrySet()[/td][td]返回此映射所包含的映射关系Set视图[/td][/tr][tr][td]get()[/td][td]返回指定键映射到的值没如果此映射不包含该键的映射关系,则返回null[/td][/tr][tr][td]isEmpty()[/td][td]此映射不包含键值则返回true[/td][/tr][tr][td]keys()[/td][td]返回此表中键的枚举[/td][/tr][tr][td]put(K key, V value)[/td][td]指定将健映射到此表中的指定值[/td][/tr][tr][td]putAll(Map
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

兜兜零元

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表