【翻译十八】java-并发之锁对象

Lock Objects

Synchronized code relies on a simple kind of reentrant lock. This kind of lock is easy to use, but has many limitations. More sophisticated locking idioms are supported by the java.util.concurrent.locks package. We won’t examine this package in detail, but instead will focus on its most basic interface, Lock.

Lock objects work very much like the implicit locks used by synchronized code. As with implicit locks, only one thread can own a Lock object at a time. Lock objects also support a wait/notify mechanism, through their associated Condition objects.

The biggest advantage of Lock objects over implicit locks is their ability to back out of an attempt to acquire a lock. The tryLock method backs out if the lock is not available immediately or before a timeout expires (if specified). ThelockInterruptibly method backs out if another thread sends an interrupt before the lock is acquired.

Let’s use Lock objects to solve the deadlock problem we saw in Liveness. Alphonse and Gaston have trained themselves to notice when a friend is about to bow. We model this improvement by requiring that our Friend objects must acquire locks for both participants before proceeding with the bow. Here is the source code for the improved model, Safelock. To demonstrate the versatility of this idiom, we assume that Alphonse and Gaston are so infatuated with their newfound ability to bow safely that they can’t stop bowing to each other:

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

public class Safelock {
    static class Friend {
        private final String name;
        private final Lock lock = new ReentrantLock();

        public Friend(String name) {
            this.name = name;
        }

        public String getName() {
            return this.name;
        }

        public boolean impendingBow(Friend bower) {
            Boolean myLock = false;
            Boolean yourLock = false;
            try {
                myLock = lock.tryLock();
                yourLock = bower.lock.tryLock();
            } finally {
                if (! (myLock && yourLock)) {
                    if (myLock) {
                        lock.unlock();
                    }
                    if (yourLock) {
                        bower.lock.unlock();
                    }
                }
            }
            return myLock && yourLock;
        }
            
        public void bow(Friend bower) {
            if (impendingBow(bower)) {
                try {
                    System.out.format("%s: %s has"
                        + " bowed to me!%n", 
                        this.name, bower.getName());
                    bower.bowBack(this);
                } finally {
                    lock.unlock();
                    bower.lock.unlock();
                }
            } else {
                System.out.format("%s: %s started"
                    + " to bow to me, but saw that"
                    + " I was already bowing to"
                    + " him.%n",
                    this.name, bower.getName());
            }
        }

        public void bowBack(Friend bower) {
            System.out.format("%s: %s has" +
                " bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    static class BowLoop implements Runnable {
        private Friend bower;
        private Friend bowee;

        public BowLoop(Friend bower, Friend bowee) {
            this.bower = bower;
            this.bowee = bowee;
        }
    
        public void run() {
            Random random = new Random();
            for (;;) {
                try {
                    Thread.sleep(random.nextInt(10));
                } catch (InterruptedException e) {}
                bowee.bow(bower);
            }
        }
    }
            

    public static void main(String[] args) {
        final Friend alphonse =
            new Friend("Alphonse");
        final Friend gaston =
            new Friend("Gaston");
        new Thread(new BowLoop(alphonse, gaston)).start();
        new Thread(new BowLoop(gaston, alphonse)).start();
    }
}

« Previous • 
Trail • 
Next »

译文:
锁对象
  同步代码依赖于一种简单的重入锁。这种锁很容易使用,但是却有很多限制。java.util.concurrent.locks包中支持许多更复杂的锁的规则。我们不会详细的校验
这个包中的东西,而是把重点放在其最基本的接口,锁上。
  锁对象的工作原理和通过同步方法严格实现的锁一样。同严格实现的锁一样,一个线程一次只能拥有一个锁对象。通过关联Condition对象,锁对象也支持wait/notify机制。
  锁对象比严格的锁最大的优势是他们能够从获得一个锁返回。tryLock方法从一个没有立即使用的锁或者超过期望时间(如果)的锁。lockInterruptibly方法会使若果另一个线程向这个锁发送一个中断请求返回。
  让我们用锁对象来解决在Liveness中出现的死锁问题。Alphone和Gaston被训练成为各自都能注意到一个朋友正在鞠躬。我们要求我们的朋友必须获得锁让后再继续鞠躬的这种改进模型。这里是这种模型的改进模型,safelock。为了证明这些规则的功能性,我们假设Alphonse和Gaston都非常痴迷于他们的新发现安全的鞠躬,他们不能互相阻止对方的鞠躬。

 1 import java.util.concurrent.locks.Lock;
 2 import java.util.concurrent.locks.ReentrantLock;
 3 import java.util.Random;
 4 
 5 public class Safelock {
 6     static class Friend {
 7         private final String name;
 8         private final Lock lock = new ReentrantLock();
 9 
10         public Friend(String name) {
11             this.name = name;
12         }
13 
14         public String getName() {
15             return this.name;
16         }
17 
18         public boolean impendingBow(Friend bower) {
19             Boolean myLock = false;
20             Boolean yourLock = false;
21             try {
22                 myLock = lock.tryLock();
23                 yourLock = bower.lock.tryLock();
24             } finally {
25                 if (! (myLock && yourLock)) {
26                     if (myLock) {
27                         lock.unlock();
28                     }
29                     if (yourLock) {
30                         bower.lock.unlock();
31                     }
32                 }
33             }
34             return myLock && yourLock;
35         }
36             
37         public void bow(Friend bower) {
38             if (impendingBow(bower)) {
39                 try {
40                     System.out.format("%s: %s has"
41                         + " bowed to me!%n", 
42                         this.name, bower.getName());
43                     bower.bowBack(this);
44                 } finally {
45                     lock.unlock();
46                     bower.lock.unlock();
47                 }
48             } else {
49                 System.out.format("%s: %s started"
50                     + " to bow to me, but saw that"
51                     + " I was already bowing to"
52                     + " him.%n",
53                     this.name, bower.getName());
54             }
55         }
56 
57         public void bowBack(Friend bower) {
58             System.out.format("%s: %s has" +
59                 " bowed back to me!%n",
60                 this.name, bower.getName());
61         }
62     }
63 
64     static class BowLoop implements Runnable {
65         private Friend bower;
66         private Friend bowee;
67 
68         public BowLoop(Friend bower, Friend bowee) {
69             this.bower = bower;
70             this.bowee = bowee;
71         }
72     
73         public void run() {
74             Random random = new Random();
75             for (;;) {
76                 try {
77                     Thread.sleep(random.nextInt(10));
78                 } catch (InterruptedException e) {}
79                 bowee.bow(bower);
80             }
81         }
82     }
83             
84 
85     public static void main(String[] args) {
86         final Friend alphonse =
87             new Friend("Alphonse");
88         final Friend gaston =
89             new Friend("Gaston");
90         new Thread(new BowLoop(alphonse, gaston)).start();
91         new Thread(new BowLoop(gaston, alphonse)).start();
92     }
93 }

养养眼^_^

《【翻译十八】java-并发之锁对象》

    原文作者:alexander.bruce.lee
    原文地址: http://www.cnblogs.com/accipiter/p/3286263.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞