使用ReentrantLock

来源:互联网 发布:苹果手机看书软件 编辑:程序博客网 时间:2024/06/05 00:31

使用ReentrantLock,最大的感触就是,一定要严格按照使用规范去写,否则各种多线程问题让人防不胜防。

大概几点吧:

1、无论是ReentrantLock还是Condition都是为了锁资源而存在的,没有资源的话,这些东西就没有意义。

2、ReentrantLock是为了保证操作资源的互斥性,Condition是为了消除等待资源的时间浪费。

3、ReentrantLock一定要lock和unlock配对出现,并且一定要保证不管走任何代码分支,都要有unlock操作。(写示例中,就在while循环内部写了lock,在外部finally写了unlock,结果死锁了)

4、必须是先增加资源,然后才释放出signal信号。


小小示例,随意看看吧~~

package lock;import java.util.LinkedList;import java.util.List;import java.util.Random;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.ReentrantLock;public class TestCondition {static ReentrantLock lock = new ReentrantLock();static int[] resource = new int[] { 0, 0, 0, 0, 0 };public static void main(String[] args) {// test1();test2();}private static void test1() {int[][][] testcase1 = new int[][][] {new int[][] { new int[] { 0, 1, 2, 3 }, new int[] { 4 } },new int[][] { new int[] { 0, 1, 2 }, new int[] { 3, 4 } },new int[][] { new int[] { 0, 1 }, new int[] { 2, 3, 4 } },new int[][] { new int[] { 0 }, new int[] { 1, 2, 3, 4 } },new int[][] { new int[] {}, new int[] { 0 } } };test(testcase1);}private static void test2() {int[][][] testcase2 = new int[][][] {new int[][] { new int[] { 0 }, new int[] { 1 } },new int[][] { new int[] { 1 }, new int[] { 2 } },new int[][] { new int[] { 2 }, new int[] { 3 } },new int[][] { new int[] { 3 }, new int[] { 4 } },new int[][] { new int[] { 4 }, new int[] { 0 } } };Condition start = test(testcase2)[0];lock.lock();resource[0]++;start.signal();lock.unlock();}static Condition[] test(int[][][] testcase) {Condition[] conditions = new Condition[resource.length];for (int i = 0; i < conditions.length; i++) {conditions[i] = lock.newCondition();}List<Thread> list = new LinkedList<Thread>();for (int[][] worker : testcase) {list.add(new Thread(new Runit(conditions, worker[0], worker[1])));}int i = 0;for (Thread t : list) {t.setName("t" + i++);t.start();}return conditions;}static class Runit implements Runnable {Condition[] cons;int[] waits;int[] signals;/** * 模拟生产线 *  * @param cons 对应resource的Condition数组 * @param wait 该生产线的原料 * @param signal 该生产线的产出 */public Runit(Condition[] cons, int[] wait, int[] signal) {this.cons = cons;this.waits = wait;this.signals = signal;}@Overridepublic void run() {while (true) {try {sleep();lock.lock(); // 锁住全部资源,不允许其他线程操作resourceif (waits != null) {for (int c : waits) {if (resource[c] <= 0) {cons[c].await(); // 发现某个资源欠缺,释放锁,等待唤醒重新竞争锁}resource[c]--; // 消耗资源}}if (signals != null) {for (int c : signals) {resource[c]++; // 产出资源System.out.println("Thread "+ Thread.currentThread().getName()+ " make a product -- " + c);cons[c].signal(); // 通知本生产线某产品制成}}} catch (Exception e) {System.out.println(e);} finally {lock.unlock(); // 释放资源锁,允许其他线程竞争resource处理资格}}}private void sleep() throws InterruptedException {Random rad = new Random();int r = rad.nextInt(4000);if (r < 0) {r = -r;}Thread.sleep(1000 + r);}}}



原创粉丝点击