并发编程(4)--显示锁和AQS

4、显式锁和AQS  

显式锁

Lock接口和核心方法

package com.xiangxue.ch4;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Administrator
 *
 *使用显示锁的范式:一定要在finally中释放锁
 */
public class LockDemo {

    private Lock lock  = new ReentrantLock();
    private int count;

    public void increament() {
        lock.lock();
        try {
            count++;
        }finally {
            lock.unlock();
        }
    }

    public synchronized void incr2() {//可重入
        count++;
        incr2();
    }

    public synchronized void test3() {//可重入
        incr2();
    }

}

1.Lock接口和synchronized的比较

synchronized 代码简洁,Lock:获取锁可以被中断,超时获取锁,尝试获取锁,读多写少用读写锁

2.可重入锁ReentrantLock、所谓锁的公平和非公平

如果在时间上,先对锁进行获取的请求,一定先被满足,这个锁就是公平的,不满足,就是非公平的

非公平的效率一般来讲更高

private Lock lock  = new ReentrantLock();构造方法可以指定公平锁还是非公平锁,默认非公平。

3.ReadWriteLock接口和读写锁ReentrantReadWriteLock

ReentrantLock和Syn关键字,都是排他锁,同一时刻,只允许同一个线程访问。

读写锁:同一时刻允许多个读线程同时访问,但是写线程访问的时候,所有的读和写都被阻塞,最适宜于读多写少的情况

4.Condition接口

5.用Lock和Condition实现等待通知

了解LockSupport工具

park开头的方法

负责阻塞线程

unpark(Thread thread)方法

负责唤醒线程

AbstractQueuedSynchronizer深入分析

什么是AQS?学习它的必要性

AQS使用方式和其中的设计模式

继承,模板方法设计模式

了解其中的方法

模板方法:

独占式获取

accquire

acquireInterruptibly

tryAcquireNanos

共享式获取

acquireShared

acquireSharedInterruptibly

tryAcquireSharedNanos

独占式释放锁

release

共享式释放锁

releaseShared

需要子类覆盖的流程方法

独占式获取  tryAcquire

独占式释放  tryRelease

共享式获取 tryAcquireShared

共享式释放  tryReleaseShared

这个同步器是否处于独占模式  isHeldExclusively

同步状态state:

getState:获取当前的同步状态

setState:设置当前同步状态

compareAndSetState 使用CAS设置状态,保证状态设置的原子性

AQS中的数据结构-节点和同步队列

竞争失败的线程会打包成Node放到同步队列,Node可能的状态里:

CANCELLED线程等待超时或者被中断了,需要从队列中移走

SIGNAL后续的节点等待状态,当前节点,通知后面的节点去运行

CONDITION :当前节点处于等待队列

PROPAGATE共享表示状态要往后面的节点传播

0, 表示初始状态

节点在同步队列中的增加和移出

独占式同步状态获取与释放

其他同步状态获取与释放

Condition分析

 

原文地址:https://www.cnblogs.com/zqLoveSym/p/12248144.html

时间: 2024-10-12 11:33:43

并发编程(4)--显示锁和AQS的相关文章

多线程并发编程之显示锁ReentrantLock和读写锁

在Java5.0之前,只有synchronized(内置锁)和volatile. Java5.0后引入了显示锁ReentrantLock. ReentrantLock概况 ReentrantLock是可重入的锁,它不同于内置锁, 它在每次使用都需要显示的加锁和解锁, 而且提供了更高级的特性:公平锁, 定时锁, 有条件锁, 可轮询锁, 可中断锁. 可以有效避免死锁的活跃性问题.ReentrantLock实现了 Lock接口: public interface Lock { //阻塞直到获得锁或者中

Java并发编程:Concurrent锁机制解析

.title { text-align: center } .todo { font-family: monospace; color: red } .done { color: green } .tag { background-color: #eee; font-family: monospace; padding: 2px; font-size: 80%; font-weight: normal } .timestamp { color: #bebebe } .timestamp-kwd

并发编程(6)基于锁的并发数据结构设计

主要内容: 并发数据结构设计的意义 指导如何设计 实现为并发设计的数据结构 如果一种数据结构可以被多个线程所访问,其要不就是绝对不变的(其值不会发生变化,并且不需同步),要不程序就要对数据结构进行正确的设计,以确保其能在多线程环境下能够(正确的)同步.一种选择是使用独立的互斥量,其可以锁住需要保护的数据,另一种选择是设计一种能够并发访问的数据结构.第一种使用互斥量,在同一时间只有一个线程可以访问数据,实际是一种串行的序列化访问.显示的组织了多线程对数据结构的并发访问. 所以,缩小保护区域,减少序

并发编程--CAS自旋锁

在前两篇博客中我们介绍了并发编程--volatile应用与原理和并发编程--synchronized的实现原理(二),接下来我们介绍一下CAS自旋锁相关的知识. 一.自旋锁提出的背景 由于在多处理器系统环境中有些资源因为其有限性,有时需要互斥访问(mutual exclusion),这时会引入锁的机制,只有获取了锁的进程才能获取资源访问.即是每次只能有且只有一个进程能获取锁,才能进入自己的临界区,同一时间不能两个或两个以上进程进入临界区,当退出临界区时释放锁.设计互斥算法时总是会面临一种情况,即

Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型

一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例子 #并发运行,效率高,但竞争同一打印终端,带来了打印错乱 from multiprocessing import Process import os,time def work(): print('%s is running' %os.getpid()) time.sleep(2) print('

高并发编程之无锁

前几期简单介绍了一些线程方面的基础知识,以及一些线程的一些基础用法以及通过jvm内存模型的方式去介绍了一些并发中常见的问题(想看往期文章的小伙伴可以直接拉到文章最下方飞速前往).本文重点介绍一个概念“无锁” 本期精彩什么是无锁无锁类的原理AtomicIntegerUnsafeAtomicReferenceAtomicStampedReference 什么是无锁 在高并发编程中最重要的就是获取临界区资源,保证其中操作的原子性.一般来说使用synchronized关键字进行加锁,但是这种操作方式其实

显示锁和aqs

一.内置锁sync 和 显示锁lock概念 1.synv锁又叫内置锁,不能中断,拿不到无限等待即阻塞: java自带关键字: 隐式可重入: 重入锁:锁对应对象要多次调用对应方法,如递归 2. lock的lockinterruptiply意思是可中断的:语言层面的接口: 其实现类reentrantlock 可重入锁,sync锁显示对应,可以理解为sync关键字在lock接口下的实现: 3.重入锁:锁对应对象要多次调用对应方法,如递归: 可重入锁,sync内置锁,多次获取和释放,计数器加1减1,方法

并发编程之互斥锁

原子性问题的源头是线程切换,如果能够禁用线程切换那不就能解决这个问题了吗?而操作系统做线程切换是依赖 CPU 中断的,所以禁止 CPU 发生中断就能够禁止线程切换. 在早期单核 CPU 时代,这个方案的确是可行的,而且也有很多应用案例,但是并不适合多核场景.这里我们以 32 位 CPU 上执行 long 型变量的写操作为例来说明这个问题,long 型变量是 64 位,在 32 位 CPU 上执行写操作会被拆分成两次写操作(写高 32 位和写低 32 位,如下图所示). 在单核 CPU 场景下,同

JAVA并发编程学习笔记------锁顺序死锁

一.需求描述: 将资金从一个账户转移到另一个账户. 二.程序实现: (1)账户类: public class Account { private long account; public Account(String user, long account) { this.account = account; } public Account() { super(); } public long getAccount() { return account; } public void setAcc