Java并发同步器AQS(AbstractQueuedSynchronizer)学习笔记(2)

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

学习了AbstractQueuedSynchronizer 之后(Condition没有在上文做笔记,当应该不难理解),接下来笔者就尝试着分析在JUC包中的各个同步器,其语义是如何实现的。

ReentrantLock

内部类Sync继承了AbstractQueuedSynchronizer。state表示锁被重入的次数。因为其是独占锁,所以只实现了tryRelease,isHeldExclusively方法,而tryAcquire则交由子类基于公平和非公平的策略来实现。

公平的ReentrantLock会在每次tryAcquire的时候,都老老实实让排在队列前面的线程优先拿锁。而非公平锁则是发现state为0后,就马上去尝试设置state,如果不能成功,才进入AQS内部的队列老老实实的排队。

ReentrantReadWriteLock

此类最为复杂。内部类Sync继承了AbstractQueuedSynchronizer,同时内部类ReadLock和WriteLock内部共享了Sync,state这个int被划分成两部分,高位16个bit表示共享读锁,低位16个bit表示独占写锁。

大概的工作方式是:读锁使用shared模式,复写tryAcquireShared和tryReleaseShared;写锁使用独占锁,复写tryAcquire和tryRelease。当线程要求锁住写锁的时候,内部会检查state是否为0;如果不为0,则检查此时是写状态还是读状态;如果是写状态,则检查持有写锁的是否是自己;如果是的话,则进行锁重入。锁住读锁也是这个道理,只不过是使用的shared的锁模式而已。

Semaphore

使用state表示信号量。可以想象,使用是的shared模式。在acquire的时候,会去比较state来判断是否可以成功。

需要注意的是此类如果使用不当,则可能会有线程被挂住的问题,测试代码可以参见这里:https://gist.github.com/3879133。

CountDownLatch

与Semaphore一样,都是非常简单的使用了state。

CyclicBarrier

内部使用的是ReentrantLock,利用了Condition来唤醒栅栏前的线程。

FutureTask

使用state来表示任务的执行状态。代码也相对比较简单。值得注意的是,FutureTask对于任务执行抛出的异常,是会捕捉住的(在get的时候才会给抛给你),如果在编写任务时候没有catch(Exception),而导致有异常漏过业务代码,则很有可能产生不可预知的问题。比如,在使用 ScheduledExecutorService分发定时任务之后,而又不关心返回结果的时候,就可能会出现问题。所以一般对自己的线程,也应该处理自己线程的异常,这也是最佳实践的原则。

原文在我的博客上:http://www.zavakid.com/207

转载于:https://my.oschina.net/zavakid/blog/85008

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/548279.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Visual C++ 2008入门经典 第四章数组 字符串

/* //学习内容 数组及其使用方法 如何声明和初始化不同类型的数组 如何声明和使用多维数组 指针及其使用方法 如果声明和初始化不同类型的指针 数组和指针之间的关系 引用的概念及声明方法,关于使用引用的几点初步建议 如何在本地C程序中给变量动态分配内存 如何在C…

[转载]ns2在linux安装过程

本安装教程,实在ubuntu下实现,安装的软件的版本,可能不同, 过程中也可能存在微小差异,供参考。 本人亲测,gcc版本4.5,ns2版本2.35,成功。 教程来源:http://blog.sina.com…

Http的轻微配置

目标: 建立DNS服务器,同时为linux.com, php.net, apache.org三个域提供解析;要求,每个域内的www主机均指向本机唯一的IP; 建立httpd服务器,分别为www.linux.com, www.php.net, www.apache.org 各提供一个虚…

Ural 1627 Join(生成树计数)

http://acm.timus.ru/problem.aspx?space1&num1627 生成树计数的题&#xff0c;直接用Matrix-Tree定理就可以解决问题了。 代码如下&#xff1a; View Code 1 #include <cstdio>2 #include <cstring>3 #include <algorithm>4 5 using namespace std;6 …

repair filesystem 一般是什么引起的和该怎样解决

repair filesystem 一般是什么引起的和该怎样解决 linux下repair filesystem模式修复方法实践 第一种情况&#xff1a;非正常关机引起的磁盘分区问题不能正常进入系统 如果确定是由于上次非正常关机或者异常断电引起的&#xff0c;可以使用fsck /dev/hdaX后reboot进入&#xff…

Navicat for MySQL工具创建mysql数据库定时器

步骤1&#xff1a; 步骤二&#xff1a; 效果图:

centos安装virtualbox

1 检查系统内核版本[rootcentos ~]# uname -aLinux centos2.6.18-194.el5 #1 SMP Fri Apr 2 14:58:35 EDT 2010 i686 i686 i386 GNU/Linux2 安装软件环境yum install gcc yum install kernel-devel yum install kernel-headers 注&#xff1a;这步执行后的版kernel-devel和kern…

带有emplace开头的STL为何优于其它插入函数

#include #include #include “my_string.h” int main() { std::vector<my_string>vec; //会执行构造函数&#xff0c;再执行move构造函数,如果没有move会自己生成默认的move构造函数 vec.push_back(“1111”); //c会执行构造&#xff0c;执行完毕 std::string str …

openssl rsa密钥

#include <boost/asio/ssl.hpp> #include #if defined(WINDOWS) #if (OPENSSL_VERSION_NUMBER > 0x10101000L) #pragma comment(lib,“libcrypto.lib”) #pragma comment(lib,“libssl.lib”) #else #pragma comment(lib,“libeay32.lib”) #pragma comment(lib,“ss…

Juniper基础系列之一---vlan的建立

VLAN是交换机最重要的一个功能。EX交换机关于VLAN配置的菜单有三层&#xff0c;首先是vlans菜单层次&#xff0c;在vlans&#xff08;通过edit vlans可以进入vlans菜单里面&#xff09;里面可以创建vlan&#xff0c;而创建vlan的时候可以指定名字和vlan id。 在EX端口下面&…

魔兽争霸3地图(WarIII Maps):三国猛兽传

魔兽争霸3地图&#xff08;WarIII Maps&#xff09;&#xff1a;三国猛兽传三国猛兽传三国时期&#xff0c;连年战乱&#xff0c;天降异象&#xff0c;所有战力无双的英雄&#xff0c;外表全都变成了凶悍的猛兽…………其貌虽毁&#xff0c;其心不改攻城略地&#xff0c;百战成…

Linux下Redis的安装、配置操作说明

Redis 是一个高性能的key-value数据库。 redis的出现&#xff0c;很大程度补偿了memcached这类keyvalue存储的不足&#xff0c;在部分场合可以对关系数据库起到很好的补充作用。它提供了Python&#xff0c;Ruby&#xff0c;Erlang&#xff0c;PHP客户端&#xff0c;使用很方便。…

提取ip和端口

#include int main() { std::string str “192.168.9:8086”; std::string buffer1; buffer1.resize(128); int port 0; sscanf(str.c_str(), “%[^:]:%d”, &buffer1[0],&port); //std::string str “https://192.168.9:8086/test”; //std::string buffer1; //b…

Oracle SQL语句执行步骤

Oracle中SQL语句执行过程中,Oracle内部解析原理如下: 1、当一用户第一次提交一个SQL表达式时,Oracle会将这SQL进行Hard parse,这过程有点像程序编译,检查语法、表名、字段名等相关信息&#xff08;如下图&#xff09;&#xff0c;这过程会花比较长的时间&#xff0c;因为它要分…

字节流及字节对齐

#include #pragma pack(push,4) struct MyStruct { unsigned char a;// unsigned int b; //到这里是&#xff0c;加起来等于unsigned int 字节的倍数 unsigned char Cbuffer[10];//char没有字节对齐 unsigned int d; }; #pragma pack() void EnCodePack(unsigned char*cSend…

Android平台各类恶意软件及病毒概览

原文请见:http://mobile.51cto.com/ahot-364267.htmAndroid平台中各类恶意软件及病毒概览<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />随着移动互联网的发展&#xff0c;作为当今最大的移动操作系统之一&#xff0c;Android已…

string封装

class String { public: String(const char*str NULL) { if (str NULL) { data_ new char[1]; data_[0] 0; //memset(data_, 0, sizeof(data_)); //数组越界&#xff0c;delete的时候&#xff0c;会影响内存回收变化&#xff0c;因此会导致程序崩溃 } else { data_ new ch…

vim高级技巧(split)_小花_新浪博客

vim高级技巧&#xff08;split&#xff09;_小花_新浪博客:res(ize) N 把当前窗口高度增加N个像素 :res(ize) -N 把当前窗口高度减少N个像素 :vertical res(ize) N 把当前窗口宽度增加N个像素 :vertical res(ize) -N 把当前窗口宽度减少N个像素等于是按下后,松开键盘,再按…

单链表反转和插入

#include struct node { int value -1; node* next_ptr nullptr; }; //创建结点 void create(int i, node** header_ptr) { node* current header_ptr; //第一个结点 if (current nullptr) { node ptr new node; ptr->value i; ptr->next_ptr nullptr; header…

liunx命令联系

1&#xff0c;liunx桌面和命令行之间的切换 init 3 init4 init5 2&#xff0c;liunx下用户的切换是su 用户 转载于:https://blog.51cto.com/lvjian118/1057319