并发之自旋锁

 1 自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时 才能进入临界区。如下
 2     private AtomicReference<Thread> sign =new AtomicReference<>();
 3     public void lock() {
 4         Thread current = Thread.currentThread();
 5         while (!sign.compareAndSet(null, current)) {
 6           }
 7     }
 8     public void unlock() {
 9         Thread current = Thread.currentThread();
10         sign.compareAndSet(current, null);
11     }
12 
13 public class Test implements Runnable {
14     static int sum;
15     private SpinLock lock;
16 
17     public Test(SpinLock lock) {
18         this.lock = lock;
19     }
20 
21     /**
22      * @param args
23      * @throws InterruptedException
24      */
25     public static void main(String[] args) throws InterruptedException {
26         SpinLock lock = new SpinLock();
27         for (int i = 0; i < 100; i++) {
28             Test test = new Test(lock);
29             Thread t = new Thread(test);
30             t.start();
31         }
32 
33         Thread.currentThread().sleep(1000);
34         System.out.println(sum);
35     }
36 
37     @Override
38     public void run() {
39         this.lock.lock();
40         this.lock.lock();
41         sum++;
42         this.lock.unlock();
43         this.lock.unlock();
44     }
45 
46 }
47 当一个线程 调用这个不可重入的自旋锁去加锁的时候没问题,当再次调用lock()的时候,因为自旋锁的持有引用已经不为空了,该线程对象会误认为是别人的线程持有了自旋锁
48 使用了CAS原子操作,lock函数将owner设置为当前线程,并且预测原来的值为空。unlock函数将owner设置为null,并且预测值为当前线程。
49 当有第二个线程调用lock操作时由于owner值不为空,导致循环一直被执行,直至第一个线程调用unlock函数将owner设置为null,第二个线程才能进入临界区。
50 由于自旋锁只是将当前线程不停地执行循环体,不进行线程状态的改变,所以响应速度更快。但当线程数不停增加时,性能下降明显,因为每个线程都需要执行,占用CPU时间。如果线程竞争不激烈,并且保持锁的时间段。适合使用自旋锁。

 

posted on 2018-10-27 11:53  jovelove  阅读(189)  评论(0)    收藏  举报