这期内容当中小编将会给大家带来有关在java项目中如何实现同步线程,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
<强> java线程同步强>
<强>概要:强>
为了加快代码的运行速度,我们采用了多线程的方法。并行的执行确实让代码变得更加高效,但随之而来的问题是,有很多个线程在程序中同时运行,如果它们同时的去修改一个对象,很可能会造成讹误的情况,这个时候我们需要用一种同步的机制来管理这些线程。
<强>(一)竞争条件强>
记得操作系统中,让我印象很深的有一张图。上面画的是一块块进程,在这些进程里面分了几个线程,所有这些线程齐刷刷统一的指向进程的资源. java中也是如此,资源会在线程间共享而不是每个线程都有一份独立的资源。在这种共享的情况下,很有可能有多个线程同时在访问一个资源,这种现象我们叫做竞争条件。
<强>(二)ReentrantLock类强>
上面的例子告诉我们,如果我们的操作不是原子操作,被打断是肯定会发生的,即使有的时候概率真的非常小,但是也并不能排除这种情况。我们不能把我们的代码变成像操作系统中的原子操作,我们能做的是为我们的代码上锁来保证安全性。在并发程序中,如果我们想要访问数据,在这之前我们先给我们的代码套一个锁,在我们使用锁的期间,我们的代码中涉及的资源就像是被“锁上了“一样,不能被其他的线程访问,知道我们打开这个锁。
在java中,同步关键字和ReentrantLock类都有这种锁的功能。我们在这里首先一起来讨论一下ReentrantLcok的功能。
<强> 1. ReentrantLock构造器强>
在这个类中,提供了两个构造器,一个是默认构造器,没什么好说的,一个是带有公平策略的构造器。这个公平策略首先他比正常的锁要慢很多,其次在有的情况下他并不是真正公平的。而且如果我们没有特殊的理由真的需要公平策略的时候,尽量不要去研究这个策略。
<强> 2。获取与释放强>
ReentrantLock myLock=新的ReentrantLock ();//创建对象 myLock.lock ();//获取锁 尝试{ … } 最后{ myLock.unlock ();//释放锁 }
一定要记得在最后中释放锁! !我们之前说过,未检查的错误会导致线程的终止。莫名其妙的终止会让程序停止向下运行,如果不把释放放最终在中,这个锁将一直得不到释放。这种道理和我们在平时框架中用包后.close()是一个道理。说到,值得一提的,当我们使用锁的时候,我们不能使用“带有资源的尝试语句”,因为这个锁并不是用亲密来关闭的。如果你不知道带有资源的尝试语句是什么,那就当我没说这句话吧。
<强> 3。锁具有可重入性强>
如果你要在递归或者循环程序中使用锁,那么就放心的用吧.ReentrantLock锁具有可重入性,他会在每次调用锁()的时候维护一个计数记录着被调用的次数,在每一次的锁调用都必须要用解锁来释放。
<强>(三)条件对象强>
通常,线程在上了锁进入临界区之后发现了一个问题,他们所需要的资源,在别的对象中被使用或者并不满足他们能执行的条件,这个时候我们需要用一个条件对象来管理这些得到了一个锁,但是不能做有用工作的线程。
如果(a> b) { a.set (b - 1); }
<强> 1。“自己困住了自己”强>
上面是一个很简单的条件判断,但是我们在并发程序中不能这样写。存在的问题是,如果在这个线程刚刚做完判断之后,另外一个线程被唤醒,并且另外一个线程在操作之后使得一个小于b(如果语句中的条件已经不再正确)。
那么这个时候我们可能想的到,我们把整个如果语句直接放在锁里面,确保自己的代码不会被打断。但是这样又存在一个问题,如果如果判断是假的,那么如果中的语句不会被执行。但是如果我们需要去执行如果中的语句,甚至我们要一直等待如果判断变的正确之后去执行如果中的语句,这时,我们突然发现,如果语句再也不会变得正确了,因为我们的锁把这个线程锁死,其他的线程没办法访问临界区并修改a和b的值让如果判断变得正确,这真的是非常尴尬,我们自己的锁把我们自己困住了,我们出不去,别人进不来。
<强> 2。条件类强>
为了解决这种情况,我们用ReentrantLock类中的newCondition方法来获取一个条件对象。
条件cd=myLock.newCondition ();在java项目中如何实现同步线程