- 浏览: 691637 次
- 性别:
- 来自: 北京
博客专栏
-
读金庸故事,品程序人生
浏览量:47234
文章分类
最新评论
-
hty881008:
LZ,你的json返回是怎么出来的,我的怎么是No messa ...
使用CXF暴露您的REST服务 -
jxFY:
赞
Apache的对象池化工具commons-pool -
wangyudong:
新版本的Wisdom RESTClient地址https:// ...
使用CXF暴露您的REST服务 -
wangyudong:
由CXF实现的微服务需要有比较好的工具去测试RESTful A ...
使用CXF暴露您的REST服务 -
spring_springdata:
可以参考最新的文档:如何在eclipse jee中检出项目并转 ...
Maven3实战笔记01环境配置与使用入门
1. 前言
之前总结的多线程的调度、并发调度、线程加锁安全等等并发包底层大都使用了线程锁机制。咱们通过锁的源码来看看JDK如何将这些资源进行加锁限制的,怎么就能做到线程集中等待后就唤醒主线程的。
2. 一段并发包源码
以下是java.util.concurrent.CyclicBarrier的底层代码片段。
private int dowait(boolean timed, long nanos) throws InterruptedException, BrokenBarrierException, TimeoutException { final ReentrantLock lock = this.lock; lock.lock(); try { ……………………省略 } finally { lock.unlock(); } }
在执行等待的时候,里面使用了ReentrantLock对其进行资源加锁,保证在代码块中使用变量、读写变量不会被别的线程打扰。
3. 轻量级锁ReentrantLock
基于以上程序我们就来看看ReentrantLock内部是如何工作的。ReentrantLock内部有个Sync类,继承自AbstractQueuedSynchronizer,基于Sync又有2个子类继承于它,而ReentrantLock就是依靠这2个Sync子类为内核实现的。代码大家直接看JDK源程序即可。
ReentrantLock的lock()方法,它的加锁方法实际上是使用的内部静态类Sync的方法,至于调用的是公平——FairSync还是不公平的——NonfairSync,这个要看构建ReentrantLock的时候的构造函数了。
NonfairSync的加锁方法实现流程是这样的:首先基于CAS——Compare and Swap原则,先将state从0尝试变成1。如果设置成功了,证明了一个事实——此时此刻,没有其他的线程持有该锁。则当前线程设置为ExclusiveOwnerThread(独家拥有线程);那么如果状态变量state设置不成功呢,则又揭示了一个事实,当前线程锁已经被其他线程所持有,那么调用acquire方法,该方法首先先尝试再次获取状态state,如果为0了,那么继续尝试设置状态为1。若成功则与此时无其他线程持有锁操作雷同。如果state依然不为0,则判断当前线程是否为独家拥有线程变量——exclusiveOwnerThread,是的话将state的值+1.如果不是,则将当前线程放入等待队列中挂起,挂起方法
public static void park(Object blocker) { Thread t = Thread.currentThread(); setBlocker(t, blocker); unsafe.park(false, 0L); setBlocker(t, null); }
FairSync的lock()方法和NonfairSync大同小异。只不过它没有获取state变量信息的过程,直接是调用acquire(1)方法请求线程锁。
ReentrantLock的unlock()方法,解锁的方法比较简单,不区分公平与不公平,都是获取当前state值,之后减去释放锁的个数,减操作后结果如果为0,表示锁可以释放了。通知队列上的那些线程,唤醒队列头线程,进行run操作。
这些加锁、解锁操作很明显都离不开队列——AbstractQueuedSynchronizer的辅助操作,将线程组织成为线程队列形式。
4. 读写锁ReentrantReadWriteLock
了解了ReentrantLock在加锁原理上使用了一把锁,一把钥匙开一把锁嘛~而如果遇到大部分操作是读操作的、而写操作比较少的时候使用ReentrantLock未免有点“奢侈”。使用ReentrantReadWriteLock——读写双锁进行读取和写入,在读多写少的场景下可以提升不少性能。它的基本工作原理是这样的:当使用读锁进行lock的时候,就算是有其他线程也进行读操作,而不是写操作的时候,线程不会阻塞,可以并行执行,和没有加lock几乎是一样的。当调用写锁的lock方法时,无论其他线程是什么性质的(读、写),都阻塞,所以这个双重锁适用于读操作频率较多、写操作频率较少的操作。咱们看个使用例子
// 读写锁 static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(); // 获得读锁-加锁 reentrantReadWriteLock.readLock().lock(); String str = listString.get(sum); reentrantReadWriteLock.readLock().unlock(); // 获得写锁-加锁 reentrantReadWriteLock.writeLock().lock(); String str = Thread.currentThread().getName() + "--write:" + sum; listString.add(str); reentrantReadWriteLock.writeLock().unlock();
因为一些特殊原因,不能将源码完整的场景全部给出,只能写出简单的使用关键的片段。
读锁的加锁源代码片段是
public final void acquireShared(int arg) { if (tryAcquireShared(arg) < 0) doAcquireShared(arg); }
写锁的加锁源码片段是
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
相比较而言,就是上面说过的一旦写锁加锁时发现有其他线程进行了操作,则将当前线程放置于线程等待队列中——之后再唤醒。而读操作锁直接进行了共享线程,并发读取。
5. 总结
综合前面几篇线程调度、多线程并发计算等等,底层都是基于加锁、抽象线程等待队列AbstractQueuedSynchronizer及其2个具体子类、CAS算法的综合体现。使用多线程并发包后我们可以构建高可用和高计算能力的分布式系统。
注意:如果没有将解锁代码写到finally块中,是有问题的!!如果发生了任何的运行时异常,会向上抛,那么锁会永远不会解除,那么造成的后果大家一定知道了。
评论
献丑献丑,见笑见笑,可惜不适合你暴力的口味哈
不过的确一直觉得用java做中央控制不靠谱,所以如果不是中央控制,多台机器的同步是依赖分布式缓存的
而且概念上来说,分布式是指多台机器,而java的并发包是工作于本虚拟机内存的,两者其实是没有关系的
不知我说的有没有一丁点道理呢??呵呵
是是是,交流,互相学习才是最大的目的。我一直再提起你的一些良言,很中肯,对于我也是好的提醒与鞭策。snake1987不必太过认真~~
建议改下题目~~
实际分布式跟java的并发包没有一毛钱的关系~
你没在构建分布式系统中用到这些并发技术,不代表别人没用过,小盆友,谦虚点。
我错了,在公司这样说话习惯了
不过的确一直觉得用java做中央控制不靠谱,所以如果不是中央控制,多台机器的同步是依赖分布式缓存的
而且概念上来说,分布式是指多台机器,而java的并发包是工作于本虚拟机内存的,两者其实是没有关系的
不知我说的有没有一丁点道理呢??呵呵
是是是,标题有点不太合适,这个笔者承认。呵呵
朋友,别那么火药味十足吧。
建议改下题目~~
实际分布式跟java的并发包没有一毛钱的关系~
有些场景是在集群系统中做节点资源调度,处理不同节点、不同客户端、不同终端的时候并发的情况确实有关系的。
这个得去招聘版块吧~~~
ReentrantLock提供了可轮询的锁请求,他可以尝试的去取得锁,如果取得成功则继续处理,取得不成功,可以等下次运行的时候处理,所以不容易产生死锁,而synchronized则一旦进入锁请求要么成功,要么一直阻塞。
synchronized块结束,或者修饰的方法结束后自动释放锁。
以下是别人的一段话:我觉得比较清晰了
http://zzhonghe.iteye.com/blog/826162
synchronized:
在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的。原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,不管用没用过5.0多线程包的程序员都能理解。
ReentrantLock:
ReentrantLock提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态。
这个回头咱们可以写一段程序一个用synchronized,一个用ReentrantLock作时间和内存上的测试
建议改下题目~~
实际分布式跟java的并发包没有一毛钱的关系~
你没在构建分布式系统中用到这些并发技术,不代表别人没用过,小盆友,谦虚点。
可惜不在北京,催悲了。
建议改下题目~~
实际分布式跟java的并发包没有一毛钱的关系~
发表评论
-
Java分布式应用学习笔记09JMX-MBean的介绍(JMX的一点点补充)
2011-10-09 09:01 73541. MBean介绍 从上一篇B ... -
Java分布式应用学习笔记08JMX规范与常用的监控场景
2011-09-13 09:17 89921. JMX规范 JMX是“Java管理扩展的”的缩写,它 ... -
Java分布式应用学习笔记07线程池应用(又名:线程池与大排档)
2011-09-07 09:00 71431. 线程池是啥子 一说到池子,大家都会想到数据库连接池那 ... -
Java分布式应用学习笔记05多线程下的并发同步器----后篇
2011-08-11 09:07 69685. CountDownLatch 很多资料上都说Coun ... -
Java分布式应用学习笔记05多线程下的并发同步器----前篇
2011-08-11 09:02 92671. 前言 JDK提供的并发包,除了上一篇提到的用于集合外 ... -
Java分布式应用学习笔记04JDK的并发包的集合总结---后篇
2011-08-02 17:21 4429唉~这一大篇blog又是只能显示部分,部分内容被截断了。。。。 ... -
Java分布式应用学习笔记04JDK的并发包的集合总结---前篇
2011-08-02 17:17 53131. 前言 平时咱们使用的HashMap、ArrayLis ... -
Java分布式应用学习笔记03JVM对多线程的资源同步和交互机制
2011-07-28 10:55 65651. 前言 既然是分布式 ... -
Java分布式应用学习笔记02再谈JVM---续
2011-07-25 09:22 3773唉~~因为blog总显示不全只能分为2个了,排版也不是很好,凑 ... -
Java分布式应用学习笔记02再谈JVM
2011-07-25 09:10 58221. 前言-为何要再谈JVM 很多人认为,分布式Java应 ... -
Java分布式应用学习笔记01分布式Java应用和SOA
2011-07-22 13:52 42021. 前言 当我们所做的 ... -
使用Memcached做分布式系统的Session存储
2011-07-01 10:12 84581. 前言 Memcache除了可以做Hibernate的 ... -
用xmemcache作为JPA(Hibernate实现)二级缓存
2011-06-30 09:44 59961. 持久层的缓存 Hibern ... -
Apache_proxy负载均衡和Session复制
2011-04-06 09:26 10772今天上网查了查资料,之前使用apache的jk模块做负载均衡。 ... -
Java基于线程的分布式(转自cjnetwork)
2011-03-22 17:50 1662java基于线程的分布式 ... -
JBoss集群配置的Session复制
2011-03-21 09:19 59171. 前言 接着上一篇总结文章提出的问题,这次通 ... -
JBoss节点的负载均衡与Mysql主从备份
2011-03-16 22:37 24321. 前言 做JavaEE企业级应用就离不开集群 ... -
在default目录下快速配置JBoss集群(Web方面) 转载
2011-03-06 10:24 2164说起JBoss集群好像很高深的样子,其实一点也不恐怖,建立一个 ...
相关推荐
Java分布式应用学习笔记02再谈JVM
Java分布式应用学习笔记
Java分布式应用学习笔记01分布式Java应用和SOA
Java分布式应用学习笔记-谈JVM
java分布式应用学习笔记05多线程下的并发同步器.pdf
Java分布式应用学习笔记07线程池应用
Java分布式应用学习笔记05多线程下的并发同步器
Java分布式学习笔记01分布式Java应用
Java分布式应用学习笔记03JVM对线程的资源同步和交互机制
Java分布式应用学习笔记09JMX-MBean的介绍
Java分布式应用学习笔记08JMX规范与各种监控场景
Java分布式应用学习笔记04JDK的并发包的集合总结
Java分布式应用学习笔记08JMX规范与各种监控场景.pdf
NULL 博文链接:https://qi04072008.iteye.com/blog/1683834
Java 分布式应用程序设计代码 对Java 分布式应用程序进行了解
Java 分布式应用程序设计
java